Revision: 8661
Author: [email protected]
Date: Fri Aug 27 07:09:23 2010
Log: CurrencyList now uses pure Java in dev mode.

This patch makes CurrencyList use a Java implementation in dev mode, which improves performance.

http://gwt-code-reviews.appspot.com/771803/show

Review by: [email protected]
http://code.google.com/p/google-web-toolkit/source/detail?r=8661

Added:
 /trunk/user/src/com/google/gwt/i18n/client/impl/CurrencyDataJso.java
Modified:
 /trunk/tools/api-checker/config/gwt20_21userApi.conf
 /trunk/user/src/com/google/gwt/i18n/client/CurrencyList.java
 /trunk/user/src/com/google/gwt/i18n/client/impl/CurrencyDataImpl.java
 /trunk/user/src/com/google/gwt/i18n/rebind/CurrencyListGenerator.java

=======================================
--- /dev/null
+++ /trunk/user/src/com/google/gwt/i18n/client/impl/CurrencyDataJso.java Fri Aug 27 07:09:23 2010
@@ -0,0 +1,81 @@
+/*
+ * 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.client.impl;
+
+import com.google.gwt.core.client.JavaScriptObject;
+import com.google.gwt.i18n.client.CurrencyData;
+
+/**
+ * JSO Overlay type that wraps currency data.
+ *
+ * The JSO is an array with three elements:
+ * <pre>
+ *   0 - ISO4217 currency code
+ *   1 - currency symbol to use for this locale
+ *   2 - flags and # of decimal digits:
+ *       d0-d2: # of decimal digits for this currency, 0-7
+ *       d3:    currency symbol goes after number, 0=before
+ *       d4:    currency symbol position is based on d3
+ *       d5:    space is forced, 0=no space present
+ *       d6:    spacing around currency symbol is based on d5
+ *   3 - portable currency symbol (optional)
+ * </pre>
+ */
+public final class CurrencyDataJso extends JavaScriptObject implements CurrencyData {
+
+  protected CurrencyDataJso() {
+  }
+
+  public native String getCurrencyCode() /*-{
+    return this[0];
+  }-*/;
+
+  public native String getCurrencySymbol() /*-{
+    return this[1];
+  }-*/;
+
+  public int getDefaultFractionDigits() {
+ return CurrencyDataImpl.getDefaultFractionDigits(getFlagsAndPrecision());
+  }
+
+  public native String getPortableCurrencySymbol() /*-{
+    return this[3] || this[1];
+  }-*/;
+
+  public boolean isDeprecated() {
+    return CurrencyDataImpl.isDeprecated(getFlagsAndPrecision());
+  }
+
+  public boolean isSpaceForced() {
+    return CurrencyDataImpl.isSpaceForced(getFlagsAndPrecision());
+  }
+
+  public boolean isSpacingFixed() {
+    return CurrencyDataImpl.isSpacingFixed(getFlagsAndPrecision());
+  }
+
+  public boolean isSymbolPositionFixed() {
+    return CurrencyDataImpl.isSymbolPositionFixed(getFlagsAndPrecision());
+  }
+
+  public boolean isSymbolPrefix() {
+    return CurrencyDataImpl.isSymbolPrefix(getFlagsAndPrecision());
+  }
+
+  private native int getFlagsAndPrecision() /*-{
+    return this[2];
+  }-*/;
+}
=======================================
--- /trunk/tools/api-checker/config/gwt20_21userApi.conf Mon Aug 16 17:56:17 2010 +++ /trunk/tools/api-checker/config/gwt20_21userApi.conf Fri Aug 27 07:09:23 2010
@@ -150,3 +150,16 @@
 # Add DateTimeFormatInfo, PredefinedFormat overrides
com.google.gwt.i18n.client.DateTimeFormat::DateTimeFormat(Ljava/lang/String;Lcom/google/gwt/i18n/client/constants/DateTimeConstants;) OVERLOADED_METHOD_CALL com.google.gwt.i18n.client.DateTimeFormat::getFormat(Ljava/lang/String;) OVERLOADED_METHOD_CALL
+
+# All protected methods that were overridden by generated classes; user shouldn't be subclassing.
+com.google.gwt.i18n.client.CurrencyList::dataMap MISSING
+com.google.gwt.i18n.client.CurrencyList::ensureCurrencyMap() MISSING
+com.google.gwt.i18n.client.CurrencyList::ensureNamesMap() MISSING
+com.google.gwt.i18n.client.CurrencyList::getEntry(Ljava/lang/String;) MISSING +com.google.gwt.i18n.client.CurrencyList::getNamesEntry(Ljava/lang/String;) MISSING +com.google.gwt.i18n.client.CurrencyList::isDeprecated(Lcom/google/gwt/i18n/client/CurrencyData;) MISSING
+com.google.gwt.i18n.client.CurrencyList::loadCurrencyMap() MISSING
+com.google.gwt.i18n.client.CurrencyList::loadNamesMap() MISSING
+com.google.gwt.i18n.client.CurrencyList::namesMap MISSING
+com.google.gwt.i18n.client.CurrencyList::overrideCurrencyMap(Lcom/google/gwt/core/client/JavaScriptObject;) MISSING +com.google.gwt.i18n.client.CurrencyList::overrideNamesMap(Lcom/google/gwt/core/client/JavaScriptObject;) MISSING
=======================================
--- /trunk/user/src/com/google/gwt/i18n/client/CurrencyList.java Thu Dec 10 15:31:32 2009 +++ /trunk/user/src/com/google/gwt/i18n/client/CurrencyList.java Fri Aug 27 07:09:23 2010
@@ -18,8 +18,11 @@

 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.JavaScriptObject;
+import com.google.gwt.i18n.client.impl.CurrencyDataImpl;

 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.Iterator;

 /**
@@ -44,34 +47,90 @@
     return CurrencyListInstance.instance;
   }

-  // This helper method exists because we can't call JSO instance methods
-  // directly from JSNI.
-  protected static boolean isDeprecated(CurrencyData currencyData) {
-    return currencyData.isDeprecated();
-  }
+  /**
+   * Add all entries in {...@code override} to the original map, replacing
+ * any existing entries. This is used by subclasses that need to slightly
+   * alter the data used by the parent locale.
+   */
+  protected static final native JavaScriptObject overrideMap(
+      JavaScriptObject original, JavaScriptObject override) /*-{
+    for (var key in override) {
+      if (override.hasOwnProperty(key)) {
+        original[key] = override[key];
+      }
+    }
+    return original;
+  }-*/;

   /**
-   * JS Object which contains a map of currency codes to CurrencyDataImpl
-   * objects.  Each currency code is assumed to be a valid JS object key.
+   * Add currency codes contained in the map to an ArrayList.
    */
-  protected JavaScriptObject dataMap;
+ private static native void loadCurrencyValuesNative(JavaScriptObject map, ArrayList<CurrencyData> collection) /*-{
+    for (var key in map) {
+      if (map.hasOwnProperty(key)) {
+        [email protected]::add(Ljava/lang/Object;)(map[key]);
+      }
+    }
+  }-*/;

   /**
-   * JS Object which contains a map of currency codes to localized currency
- * names. This is kept separate from {...@link #dataMap} above so that the names
-   * can be completely removed by the compiler if they are not used. Each
-   * currency code is assumed to be a valid JS object key.
+   * Directly reference an entry in the currency names map JSO.
+   *
+   * @param code ISO4217 currency code
+   * @return currency name, or the currency code if not known
    */
-  protected JavaScriptObject namesMap;
-
+ private static native String lookupNameNative(JavaScriptObject namesMap, String code) /*-{
+    return namesMap[code] || code;
+  }-*/;
+
+  /**
+   * Directly reference an entry in the currency map JSO.
+   *
+   * @param code ISO4217 currency code
+   * @return currency data
+   */
+ private static native CurrencyData lookupNative(JavaScriptObject dataMap, String code) /*-{
+    return dataMap[code];
+  }-*/;
+
+  /**
+   * Map of currency codes to CurrencyData.
+   */
+  protected HashMap<String, CurrencyData> dataMapJava;
+
+  /**
+ * JS map of currency codes to CurrencyData objects. Each currency code is
+   * assumed to be a valid JS object key.
+   */
+  protected JavaScriptObject dataMapNative;
+
+  /**
+ * Map of currency codes to localized currency names. This is kept separate + * from {...@link #dataMap} above so that the names can be completely removed by
+   * the compiler if they are not used.
+   */
+  protected HashMap<String, String> namesMapJava;
+
+  /**
+ * JS map of currency codes to localized currency names. This is kept separate
+   * from {...@link #dataMapNative} above so that the names can be completely
+ * removed by the compiler if they are not used. Each currency code is assumed
+   * to be a valid JS object key.
+   */
+  protected JavaScriptObject namesMapNative;
+
   /**
    * Return the default currency data for this locale.
    *
    * Generated implementations override this method.
    */
-  public native CurrencyData getDefault() /*-{
-    return [ "USD", "$", 2, "US$" ];
-  }-*/;
+  public CurrencyData getDefault() {
+    if (GWT.isScript()) {
+      return getDefaultNative();
+    } else {
+      return getDefaultJava();
+    }
+  }

   /**
    * Returns an iterator for the list of currencies.
@@ -81,7 +140,7 @@
   public final Iterator<CurrencyData> iterator() {
     return iterator(false);
   }
-
+
   /**
    * Returns an iterator for the list of currencies, optionally including
    * deprecated ones.
@@ -90,23 +149,24 @@
    */
   public final Iterator<CurrencyData> iterator(boolean includeDeprecated) {
     ensureCurrencyMap();
-    ArrayList<String> keys = new ArrayList<String>();
-    loadCurrencyKeys(keys, includeDeprecated);
-    final Iterator<String> it = keys.iterator();
-    return new Iterator<CurrencyData>() {
-
-      public boolean hasNext() {
-        return it.hasNext();
-      }
-
-      public CurrencyData next() {
-        return getEntry(it.next());
-      }
-
-      public void remove() {
-        throw new UnsupportedOperationException("Remove not supported");
-      }
-    };
+    ArrayList<CurrencyData> collection = new ArrayList<CurrencyData>();
+    if (GWT.isScript()) {
+      loadCurrencyValuesNative(dataMapNative, collection);
+    } else {
+      for (CurrencyData item : dataMapJava.values()) {
+        collection.add(item);
+      }
+    }
+    if (!includeDeprecated) {
+ ArrayList<CurrencyData> newCollection = new ArrayList<CurrencyData>();
+      for (CurrencyData value : collection) {
+        if (!value.isDeprecated()) {
+          newCollection.add(value);
+        }
+      }
+      collection = newCollection;
+    }
+    return Collections.unmodifiableList(collection).iterator();
   }

   /**
@@ -117,7 +177,11 @@
    */
   public final CurrencyData lookup(String currencyCode) {
     ensureCurrencyMap();
-    return getEntry(currencyCode);
+    if (GWT.isScript()) {
+      return lookupNative(dataMapNative, currencyCode);
+    } else {
+      return dataMapJava.get(currencyCode);
+    }
   }

   /**
@@ -128,120 +192,115 @@
    */
   public final String lookupName(String currencyCode) {
     ensureNamesMap();
-    return getNamesEntry(currencyCode);
-  }
-
-  /**
-   * Ensure that the map of currency data has been initialized.
-   */
-  protected final void ensureCurrencyMap() {
-    if (dataMap == null) {
-      loadCurrencyMap();
+    if (GWT.isScript()) {
+      return lookupNameNative(namesMapNative, currencyCode);
+    } else {
+      String result = namesMapJava.get(currencyCode);
+      return (result == null) ? currencyCode : result;
     }
   }

   /**
-   * Ensure that the map of currency data has been initialized.
+   * Return the default currency data for this locale.
+   *
+   * Generated implementations override this method.
    */
-  protected final void ensureNamesMap() {
-    if (namesMap == null) {
-      loadNamesMap();
-    }
+  protected CurrencyData getDefaultJava() {
+    return new CurrencyDataImpl("USD", "$", 2, "US$");
   }

   /**
-   * Directly reference an entry in the currency map JSO.
+   * Return the default currency data for this locale.
    *
-   * @param code ISO4217 currency code
-   * @return currency data
+   * Generated implementations override this method.
    */
-  protected final native CurrencyData getEntry(String code) /*-{
-    return [email protected]::dataMap[code];
+  protected native CurrencyData getDefaultNative() /*-{
+    return [ "USD", "$", 2, "US$" ];
   }-*/;

   /**
-   * Directly reference an entry in the currency names map JSO.
+   * Loads the currency map.
    *
-   * @param code ISO4217 currency code
-   * @return currency name, or the currency code if not known
+   * Generated implementations override this method.
    */
-  protected final native String getNamesEntry(String code) /*-{
- return [email protected]::namesMap[code] | | code;
-  }-*/;
+  protected HashMap<String, CurrencyData> loadCurrencyMapJava() {
+ HashMap<String, CurrencyData> result = new HashMap<String, CurrencyData>();
+    result.put("USD", new CurrencyDataImpl("USD", "$", 2));
+    result.put("EUR", new CurrencyDataImpl("EUR", "€", 2));
+    result.put("GBP", new CurrencyDataImpl("GBP", "UK£", 2));
+    result.put("JPY", new CurrencyDataImpl("JPY", "¥", 0));
+    return result;
+  }

   /**
    * Loads the currency map from a JS object literal.
    *
    * Generated implementations override this method.
    */
-  protected native void loadCurrencyMap() /*-{
-    [email protected]::dataMap = {
-        "USD": [ "USD", "$", 2 ],
-        "EUR": [ "EUR", "€", 2 ],
-        "GBP": [ "GBP", "UK£", 2 ],
-        "JPY": [ "JPY", "¥", 0 ],
-     };
+  protected native JavaScriptObject loadCurrencyMapNative() /*-{
+    return {
+      "USD": [ "USD", "$", 2 ],
+      "EUR": [ "EUR", "€", 2 ],
+      "GBP": [ "GBP", "UK£", 2 ],
+      "JPY": [ "JPY", "¥", 0 ],
+    };
   }-*/;

   /**
-   * Loads the currency names map from a JS object literal.
+   * Loads the currency names map.
    *
    * Generated implementations override this method.
    */
-  protected native void loadNamesMap() /*-{
-    [email protected]::namesMap = {
-        "USD": "US Dollar",
-        "EUR": "Euro",
-        "GBP": "British Pound Sterling",
-        "JPY": "Japanese Yen",
-     };
-  }-*/;
-
+  protected HashMap<String, String> loadNamesMapJava() {
+    HashMap<String, String> result = new HashMap<String, String>();
+    result.put("USD", "US Dollar");
+    result.put("EUR", "Euro");
+    result.put("GBP", "British Pound Sterling");
+    result.put("JPY", "Japanese Yen");
+    return result;
+  }
+
   /**
- * Add all entries in {...@code override} to the currency data map, replacing - * any existing entries. This is used by subclasses that need to slightly
-   * alter the data used by the parent locale.
+   * Loads the currency names map from a JS object literal.
    *
-   * @param override JS object with currency code -> CurrencyData pairs
+   * Generated implementations override this method.
    */
- protected final native void overrideCurrencyMap(JavaScriptObject override) /*-{
-    var map = [email protected]::dataMap;
-    for (var key in override) {
-      if (override.hasOwnProperty(key)) {
-        map[key] = override[key];
-      }
-    }
+  protected native JavaScriptObject loadNamesMapNative() /*-{
+    return {
+      "USD": "US Dollar",
+      "EUR": "Euro",
+      "GBP": "British Pound Sterling",
+      "JPY": "Japanese Yen",
+    };
   }-*/;

   /**
- * Add all entries in {...@code override} to the currency name map, replacing - * any existing entries. This is used by subclasses that need to slightly
-   * alter the data used by the parent locale.
-   *
-   * @param override JS object with currency code -> name pairs
+   * Ensure that the map of currency data has been initialized.
    */
- protected final native void overrideNamesMap(JavaScriptObject override) /*-{
-    var map = [email protected]::namesMap;
-    for (var key in override) {
-      if (override.hasOwnProperty(key)) {
-        map[key] = override[key];
+  private void ensureCurrencyMap() {
+    if (GWT.isScript()) {
+      if (dataMapNative == null) {
+        dataMapNative = loadCurrencyMapNative();
+      }
+    } else {
+      if (dataMapJava == null) {
+        dataMapJava = loadCurrencyMapJava();
       }
     }
-  }-*/;
+  }

   /**
-   * Add currency codes contained in the map to an ArrayList.
+   * Ensure that the map of currency data has been initialized.
    */
-  private native void loadCurrencyKeys(ArrayList<String> keys,
-      boolean includeDeprecated) /*-{
-    var map = [email protected]::dataMap;
-    for (var key in map) {
-      if (map.hasOwnProperty(key)) {
-        if (includeDeprecated
- | | [email protected]::isDeprecated(Lcom/google/gwt/i18n/client/CurrencyData;)(map[key])) {
-          [email protected]::add(Ljava/lang/Object;)(key);
-        }
+  private void ensureNamesMap() {
+    if (GWT.isScript()) {
+      if (namesMapNative == null) {
+        namesMapNative = loadNamesMapNative();
+      }
+    } else {
+      if (namesMapJava == null) {
+        namesMapJava = loadNamesMapJava();
       }
     }
-  }-*/;
-}
+  }
+}
=======================================
--- /trunk/user/src/com/google/gwt/i18n/client/impl/CurrencyDataImpl.java Thu Dec 10 15:31:32 2009 +++ /trunk/user/src/com/google/gwt/i18n/client/impl/CurrencyDataImpl.java Fri Aug 27 07:09:23 2010
@@ -15,77 +15,108 @@
  */
 package com.google.gwt.i18n.client.impl;

-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.i18n.client.CurrencyData;
+import com.google.gwt.i18n.client.DefaultCurrencyData;

 /**
- * JSO Overlay type that wraps currency data.
- *
- * The JSO is an array with three elements:
- *   0 - ISO4217 currency code
- *   1 - currency symbol to use for this locale
- *   2 - flags and # of decimal digits:
- *       d0-d2: # of decimal digits for this currency, 0-7
- *       d3:    currency symbol goes after number, 0=before
- *       d4:    currency symbol position is based on d3
- *       d5:    space is forced, 0=no space present
- *       d6:    spacing around currency symbol is based on d5
- *   3 - portable currency symbol (optional)
+ * A POJO for currency data.
  */
-public final class CurrencyDataImpl extends JavaScriptObject
-    implements CurrencyData {
-
+public final class CurrencyDataImpl extends DefaultCurrencyData {
+
   /**
    * Public so CurrencyListGenerator can get to them. As usual with an impl
    * package, external code should not rely on these values.
    */
+  public static final int DEPRECATED_FLAG = 128;
   public static final int POS_FIXED_FLAG = 16;
   public static final int POS_SUFFIX_FLAG = 8;
   public static final int PRECISION_MASK = 7;
   public static final int SPACE_FORCED_FLAG = 32;
   public static final int SPACING_FIXED_FLAG = 64;
-  public static final int DEPRECATED_FLAG = 128;
-
-  protected CurrencyDataImpl() {
+
+  public static int getDefaultFractionDigits(int flagsAndPrecision) {
+    return flagsAndPrecision & PRECISION_MASK;
   }

-  public native String getCurrencyCode() /*-{
-    return this[0];
-  }-*/;
-
-  public native String getCurrencySymbol() /*-{
-    return this[1];
-  }-*/;
+  public static boolean isDeprecated(int flagsAndPrecision) {
+    return (flagsAndPrecision & DEPRECATED_FLAG) != 0;
+  }
+
+  public static boolean isSpaceForced(int flagsAndPrecision) {
+    return (flagsAndPrecision & SPACE_FORCED_FLAG) != 0;
+  }
+
+  public static boolean isSpacingFixed(int flagsAndPrecision) {
+    return (flagsAndPrecision & SPACING_FIXED_FLAG) != 0;
+  }
+
+  public static boolean isSymbolPositionFixed(int flagsAndPrecision) {
+    return (flagsAndPrecision & POS_FIXED_FLAG) != 0;
+  }
+
+  public static boolean isSymbolPrefix(int flagsAndPrecision) {
+    return (flagsAndPrecision & POS_SUFFIX_FLAG) != 0;
+  }
+
+  /**
+   * Flags and # of decimal digits.
+   *
+   * <pre>
+   *       d0-d2: # of decimal digits for this currency, 0-7
+   *       d3:    currency symbol goes after number, 0=before
+   *       d4:    currency symbol position is based on d3
+   *       d5:    space is forced, 0=no space present
+   *       d6:    spacing around currency symbol is based on d5
+   * </pre>
+   */
+  private final int flagsAndPrecision;
+
+  /**
+   * Portable currency symbol, may be the same as {...@link #currencySymbol}.
+   */
+  private final String portableCurrencySymbol;
+
+  /**
+ * Create a new CurrencyData whose portable symbol is the same as its local
+   * symbol.
+   */
+  public CurrencyDataImpl(String currencyCode, String currencySymbol,
+      int flagsAndPrecision) {
+    this(currencyCode, currencySymbol, flagsAndPrecision, currencySymbol);
+  }
+
+  public CurrencyDataImpl(String currencyCode, String currencySymbol,
+      int flagsAndPrecision, String portableCurrencySymbol) {
+    super(currencyCode, currencySymbol,
+        getDefaultFractionDigits(flagsAndPrecision));
+    this.flagsAndPrecision = flagsAndPrecision;
+    this.portableCurrencySymbol = portableCurrencySymbol;
+  }

   public int getDefaultFractionDigits() {
-    return getFlagsAndPrecision() & PRECISION_MASK;
+    return getDefaultFractionDigits(flagsAndPrecision);
   }

-  public native String getPortableCurrencySymbol() /*-{
-    return this[3] || this[1];
-  }-*/;
+  public String getPortableCurrencySymbol() {
+    return portableCurrencySymbol;
+  }

   public boolean isDeprecated() {
-    return (getFlagsAndPrecision() & DEPRECATED_FLAG) != 0;
-  }
-
+    return isDeprecated(flagsAndPrecision);
+  }
+
   public boolean isSpaceForced() {
-    return (getFlagsAndPrecision() & SPACE_FORCED_FLAG) != 0;
-  }
-
+    return isSpaceForced(flagsAndPrecision);
+  }
+
   public boolean isSpacingFixed() {
-    return (getFlagsAndPrecision() & SPACING_FIXED_FLAG) != 0;
-  }
-
+    return isSpacingFixed(flagsAndPrecision);
+  }
+
   public boolean isSymbolPositionFixed() {
-    return (getFlagsAndPrecision() & POS_FIXED_FLAG) != 0;
-  }
-
+    return isSymbolPositionFixed(flagsAndPrecision);
+  }
+
   public boolean isSymbolPrefix() {
-    return (getFlagsAndPrecision() & POS_SUFFIX_FLAG) != 0;
-  }
-
-  private native int getFlagsAndPrecision() /*-{
-    return this[2];
-  }-*/;
-}
+    return isSymbolPrefix(flagsAndPrecision);
+  }
+}
=======================================
--- /trunk/user/src/com/google/gwt/i18n/rebind/CurrencyListGenerator.java Thu Dec 10 15:31:32 2009 +++ /trunk/user/src/com/google/gwt/i18n/rebind/CurrencyListGenerator.java Fri Aug 27 07:09:23 2010
@@ -15,6 +15,7 @@
  */
 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;
@@ -189,6 +190,16 @@
     public int getFlags() {
       return flags;
     }
+
+    public String getJava() {
+      StringBuilder buf = new StringBuilder();
+ buf.append("new CurrencyDataImpl(\"").append(quote(code)).append("\", \"");
+      buf.append(quote(symbol)).append("\", ").append(flags);
+      if (portableSymbol.length() > 0) {
+        buf.append(", \"").append(quote(portableSymbol)).append('\"');
+      }
+      return buf.append(')').toString();
+    }

     public String getJson() {
       StringBuilder buf = new StringBuilder();
@@ -227,6 +238,10 @@

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
@@ -374,13 +389,10 @@
       ClassSourceFileComposerFactory factory =
           new ClassSourceFileComposerFactory(packageName, className);
       factory.setSuperclass(superClassName);
-      factory.addImport(CURRENCY_LIST);
       factory.addImport(CURRENCY_DATA);
+      factory.addImport(JAVASCRIPTOBJECT);
+      factory.addImport(HASHMAP);
       SourceWriter writer = factory.createSourceWriter(context, pw);
-      if (currencies.length > 0) {
- writeCurrencyMethod(className, writer, currencies, allCurrencyData);
-        writeNamesMethod(className, writer, currencies, allCurrencyData);
-      }
       if (defCurrencyCode != null) {
         CurrencyInfo currencyInfo = allCurrencyData.get(defCurrencyCode);
         if (currencyInfo == null) {
@@ -390,10 +402,21 @@
         }
         writer.println();
         writer.println("@Override");
-        writer.println("public native CurrencyData getDefault() /*-{");
+        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;
@@ -422,30 +445,47 @@
       ClassSourceFileComposerFactory factory =
           new ClassSourceFileComposerFactory(packageName, className);
       factory.setSuperclass(targetClass.getQualifiedSourceName());
-      factory.addImport(CURRENCY_LIST);
       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("public CurrencyData getDefault() {");
+      writer.println("protected CurrencyData getDefaultJava() {");
       writer.println("  ensureInstance();");
-      writer.println("  return instance.getDefault();");
+      writer.println("  return instance.getDefaultJava();");
       writer.println("}");
       writer.println();
       writer.println("@Override");
-      writer.println("protected void loadCurrencyMap() {");
+      writer.println("protected CurrencyData getDefaultNative() {");
       writer.println("  ensureInstance();");
-      writer.println("  instance.loadCurrencyMap();");
-      writer.println("  dataMap = instance.dataMap;");
+      writer.println("  return instance.getDefaultNative();");
       writer.println("}");
       writer.println();
       writer.println("@Override");
-      writer.println("protected void loadNamesMap() {");
+ writer.println("protected HashMap<String, CurrencyData> loadCurrencyMapJava() {");
       writer.println("  ensureInstance();");
-      writer.println("  instance.loadNamesMap();");
-      writer.println("  namesMap = instance.namesMap;");
+      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<String, String> 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() {");
@@ -619,7 +659,7 @@
   }

   /**
-   * Writes a loadCurrencyMap method for the current locale, based on its
+ * 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.
    *
@@ -627,33 +667,72 @@
    * method is omitted entirely.
    *
    * @param allCurrencyData map of currency codes to currency data for the
-   *        current locale, including all inherited currencies data
+   *          current locale, including all inherited currencies data
    * @param className name of the class we are generating
    * @param writer SourceWriter instance to use for writing the class
* @param currencies array of valid currency names in the order they should be
-   *        listed
+   *          listed
    */
-  private void writeCurrencyMethod(String className, SourceWriter writer,
+  private void writeCurrencyMethodJava(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);
       if (needHeader) {
         needHeader = false;
         writer.println();
-        writer.println("private void loadSuperCurrencyMap() {");
-        writer.println("  super.loadCurrencyMap();");
-        writer.println("}");
+        writer.println("@Override");
+ writer.println("protected HashMap<String, CurrencyData> loadCurrencyMapJava() {");
+        writer.indent();
+ writer.println("HashMap<String, CurrencyData> 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 allCurrencyData map of currency codes to currency data for the
+   *          current locale, including all inherited currencies data
+   * @param className name of the class we are generating
+   * @param writer SourceWriter instance to use for writing the class
+ * @param currencies array of valid currency names in the order they should be
+   *          listed
+   */
+  private void writeCurrencyMethodNative(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);
+      if (needHeader) {
+        needHeader = false;
         writer.println();
         writer.println("@Override");
-        writer.println("protected native void loadCurrencyMap() /*-{");
+ writer.println("protected JavaScriptObject loadCurrencyMapNative() {");
         writer.indent();
-        writer.println("[email protected]." + className
-            + "::loadSuperCurrencyMap()();");
-        writer.println("[email protected]." + className
-            + "::overrideCurrencyMap(Lcom/google/gwt/core/client/"
-            + "JavaScriptObject;)({");
+ 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) + "\": "
@@ -661,14 +740,14 @@
     }
     if (!needHeader) {
       writer.outdent();
-      writer.println("});");
+      writer.println("};");
       writer.outdent();
       writer.println("}-*/;");
     }
   }

   /**
-   * Writes a loadNamesMap method for the current locale, based on its the
+ * 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
@@ -677,31 +756,69 @@
    * @param className name of the class we are generating
    * @param writer SourceWriter instance to use for writing the class
* @param currencies array of valid currency names in the order they should be
-   *        listed
+   *          listed
    */
-  private void writeNamesMethod(String className, SourceWriter writer,
-      String[] currencies, Map<String, CurrencyInfo> allCurrencyData) {
+ 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("private void loadSuperNamesMap() {");
-          writer.println("  super.loadNamesMap();");
-          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).
+   *
+ * If no new names are added for this locale over its superclass, the method
+   * is omitted entirely.
+   *
+   * @param className name of the class we are generating
+   * @param writer SourceWriter instance to use for writing the class
+ * @param currencies array of valid currency names in the order they should be
+   *          listed
+   */
+ 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 native void loadNamesMap() /*-{");
+ writer.println("protected JavaScriptObject loadNamesMapNative() {");
           writer.indent();
-          writer.println("[email protected]." + className
-              + "::loadSuperNamesMap()();");
-          writer.println("[email protected]." + className
-              + "::overrideNamesMap(Lcom/google/gwt/core/"
-              + "client/JavaScriptObject;)({");
+ 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) + "\",");
@@ -709,7 +826,7 @@
     }
     if (!needHeader) {
       writer.outdent();
-      writer.println("});");
+      writer.println("};");
       writer.outdent();
       writer.println("}-*/;");
     }

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to