Add simple and global currency patterns.

Review by: shanjian@google.com

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10742 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/i18n/client/CurrencyData.java b/user/src/com/google/gwt/i18n/client/CurrencyData.java
index 0e286f5..a2dae16 100644
--- a/user/src/com/google/gwt/i18n/client/CurrencyData.java
+++ b/user/src/com/google/gwt/i18n/client/CurrencyData.java
@@ -43,6 +43,13 @@
   String getPortableCurrencySymbol();
 
   /**
+   * Returns the simplest symbol to use for this currency, which is not guaranteed
+   * to be unique -- for example, this might return "$" for both USD and CAD.  It
+   * is acceptable to return the same value as {@link #getCurrencySymbol()}.
+   */
+  String getSimpleCurrencySymbol();
+
+  /**
    * Returns true if this currency is deprecated and should not be returned by
    * default in currency lists.
    */
diff --git a/user/src/com/google/gwt/i18n/client/CurrencyList.java b/user/src/com/google/gwt/i18n/client/CurrencyList.java
index 0dbf144..ad5a5a3 100644
--- a/user/src/com/google/gwt/i18n/client/CurrencyList.java
+++ b/user/src/com/google/gwt/i18n/client/CurrencyList.java
@@ -137,6 +137,7 @@
    * 
    * Deprecated currencies will not be included.
    */
+  @Override
   public final Iterator<CurrencyData> iterator() {
     return iterator(false);
   }
@@ -206,7 +207,7 @@
    * Generated implementations override this method.
    */
   protected CurrencyData getDefaultJava() {
-    return new CurrencyDataImpl("USD", "$", 2, "US$");
+    return new CurrencyDataImpl("USD", "$", 2, "US$", "$");
   }
 
   /**
@@ -225,10 +226,10 @@
    */
   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));
+    result.put("USD", new CurrencyDataImpl("USD", "$", 2, "US$", "$"));
+    result.put("EUR", new CurrencyDataImpl("EUR", "€", 2, "€", "€"));
+    result.put("GBP", new CurrencyDataImpl("GBP", "UK£", 2, "UK£", "£"));
+    result.put("JPY", new CurrencyDataImpl("JPY", "¥", 0, "JP¥", "¥"));
     return result;
   }
 
diff --git a/user/src/com/google/gwt/i18n/client/DefaultCurrencyData.java b/user/src/com/google/gwt/i18n/client/DefaultCurrencyData.java
index 23f7456..05fbf79 100644
--- a/user/src/com/google/gwt/i18n/client/DefaultCurrencyData.java
+++ b/user/src/com/google/gwt/i18n/client/DefaultCurrencyData.java
@@ -54,38 +54,52 @@
     this.fractionDigits = fractionDigits;
   }
 
+  @Override
   public String getCurrencyCode() {
     return currencyCode;
   }
 
+  @Override
   public String getCurrencySymbol() {
     return currencySymbol;
   }
 
+  @Override
   public int getDefaultFractionDigits() {
     return fractionDigits;
   }
 
+  @Override
   public String getPortableCurrencySymbol() {
     return getCurrencySymbol();
   }
 
+  @Override
+  public String getSimpleCurrencySymbol() {
+    return getCurrencySymbol();
+  }
+
+  @Override
   public boolean isDeprecated() {
     return false;
   }
 
+  @Override
   public boolean isSpaceForced() {
     return false;
   }
 
+  @Override
   public boolean isSpacingFixed() {
     return false;
   }
 
+  @Override
   public boolean isSymbolPositionFixed() {
     return false;
   }
 
+  @Override
   public boolean isSymbolPrefix() {
     return false;
   }
diff --git a/user/src/com/google/gwt/i18n/client/NumberFormat.java b/user/src/com/google/gwt/i18n/client/NumberFormat.java
index c7c5ff6..5424ed3 100644
--- a/user/src/com/google/gwt/i18n/client/NumberFormat.java
+++ b/user/src/com/google/gwt/i18n/client/NumberFormat.java
@@ -321,17 +321,17 @@
   private static NumberFormat cachedPercentFormat;
   private static NumberFormat cachedScientificFormat;
 
+  // Constants for characters used in programmatic (unlocalized) patterns.
+  private static final char CURRENCY_SIGN = '\u00A4';
+
   // Number constants mapped to use latin digits/separators.
   private static NumberConstants latinNumberConstants = null;
-
   // Localized characters for dot and comma in number patterns, used to produce
   // the latin mapping for arbitrary locales.  Any separator not in either of
   // these strings will be mapped to non-breaking space (U+00A0).
   private static final String LOCALIZED_COMMA_EQUIVALENTS = ",\u060C\u066B\u3001\uFE10\uFE11\uFE50\uFE51\uFF0C\uFF64";
-  private static final String LOCALIZED_DOT_EQUIVALENTS = ".\u2024\u3002\uFE12\uFE52\uFF0E\uFF61";
 
-  // Constants for characters used in programmatic (unlocalized) patterns.
-  private static final char CURRENCY_SIGN = '\u00A4';
+  private static final String LOCALIZED_DOT_EQUIVALENTS = ".\u2024\u3002\uFE12\uFE52\uFF0E\uFF61";
   private static final char PATTERN_DECIMAL_SEPARATOR = '.';
   private static final char PATTERN_DIGIT = '#';
   private static final char PATTERN_EXPONENT = 'E';
@@ -353,26 +353,25 @@
   }
 
   /**
-   * Provides the standard currency format for the default locale.
+   * Provides the standard currency format for the current locale.
    *
    * @return a <code>NumberFormat</code> capable of producing and consuming
    *         currency format for the default locale
    */
   public static NumberFormat getCurrencyFormat() {
     if (cachedCurrencyFormat == null) {
-      cachedCurrencyFormat = new NumberFormat(
-          defaultNumberConstants.currencyPattern(), CurrencyList.get().getDefault(), false);
+      cachedCurrencyFormat = getCurrencyFormat(CurrencyList.get().getDefault());
     }
     return cachedCurrencyFormat;
   }
 
   /**
-   * Provides the standard currency format for the default locale using a
+   * Provides the standard currency format for the current locale using a
    * specified currency.
    *
    * @param currencyData currency data to use
    * @return a <code>NumberFormat</code> capable of producing and consuming
-   *         currency format for the default locale
+   *         currency format for the current locale
    */
   public static NumberFormat getCurrencyFormat(CurrencyData currencyData) {
     return new NumberFormat(defaultNumberConstants.currencyPattern(),
@@ -380,21 +379,20 @@
   }
 
   /**
-   * Provides the standard currency format for the default locale using a
+   * Provides the standard currency format for the current locale using a
    * specified currency.
    *
    * @param currencyCode valid currency code, as defined in
    *     com.google.gwt.i18n.client.constants.CurrencyCodeMapConstants.properties
    * @return a <code>NumberFormat</code> capable of producing and consuming
-   *         currency format for the default locale
+   *         currency format for the current locale
    * @throws IllegalArgumentException if the currency code is unknown
    */
   public static NumberFormat getCurrencyFormat(String currencyCode) {
-    // TODO(jat): consider caching values per currency code.
-    return new NumberFormat(defaultNumberConstants.currencyPattern(),
-        lookupCurrency(currencyCode), false);
+    return getCurrencyFormat(lookupCurrency(currencyCode));
   }
 
+
   /**
    * Provides the standard decimal format for the default locale.
    *
@@ -451,6 +449,44 @@
   }
 
   /**
+   * Provides the global currency format for the current locale, using its
+   * default currency.
+   * 
+   * @return a <code>NumberFormat</code> capable of producing and consuming
+   *         currency format for the current locale
+   */
+  public static NumberFormat getGlobalCurrencyFormat() {
+    return getGlobalCurrencyFormat(CurrencyList.get().getDefault());
+  }
+
+  /**
+   * Provides the global currency format for the current locale, using a
+   * specified currency.
+   *
+   * @param currencyData currency data to use
+   * @return a <code>NumberFormat</code> capable of producing and consuming
+   *         currency format for the current locale
+   */
+  public static NumberFormat getGlobalCurrencyFormat(CurrencyData currencyData) {
+    return new NumberFormat(defaultNumberConstants.globalCurrencyPattern(),
+        currencyData, false);
+  }
+  
+  /**
+   * Provides the global currency format for the current locale, using a
+   * specified currency.
+   *
+   * @param currencyCode valid currency code, as defined in
+   *     com.google.gwt.i18n.client.constants.CurrencyCodeMapConstants.properties
+   * @return a <code>NumberFormat</code> capable of producing and consuming
+   *         currency format for the current locale
+   * @throws IllegalArgumentException if the currency code is unknown
+   */
+  public static NumberFormat getGlobalCurrencyFormat(String currencyCode) {
+    return getGlobalCurrencyFormat(lookupCurrency(currencyCode));
+  }
+
+  /**
    * Provides the standard percent format for the default locale.
    *
    * @return a <code>NumberFormat</code> capable of producing and consuming
@@ -481,6 +517,48 @@
   }
 
   /**
+   * Provides the simple currency format for the current locale using its
+   * default currency. Note that these formats may be ambiguous if the
+   * currency isn't clear from other content on the page.
+   *
+   * @return a <code>NumberFormat</code> capable of producing and consuming
+   *         currency format for the current locale
+   */
+  public static NumberFormat getSimpleCurrencyFormat() {
+    return getSimpleCurrencyFormat(CurrencyList.get().getDefault());
+  }
+
+  /**
+   * Provides the simple currency format for the current locale using a
+   * specified currency. Note that these formats may be ambiguous if the
+   * currency isn't clear from other content on the page.
+   *
+   * @param currencyData currency data to use
+   * @return a <code>NumberFormat</code> capable of producing and consuming
+   *         currency format for the current locale
+   */
+  public static NumberFormat getSimpleCurrencyFormat(CurrencyData currencyData) {
+    return new NumberFormat(defaultNumberConstants.simpleCurrencyPattern(),
+        currencyData, false);
+  }
+
+  /**
+   * Provides the simple currency format for the current locale using a
+   * specified currency. Note that these formats may be ambiguous if the
+   * currency isn't clear from other content on the page.
+   * 
+   * @param currencyCode valid currency code, as defined in
+   *        com.google.gwt.i18n.client
+   *        .constants.CurrencyCodeMapConstants.properties
+   * @return a <code>NumberFormat</code> capable of producing and consuming
+   *         currency format for the current locale
+   * @throws IllegalArgumentException if the currency code is unknown
+   */
+  public static NumberFormat getSimpleCurrencyFormat(String currencyCode) {
+    return getSimpleCurrencyFormat(lookupCurrency(currencyCode));
+  }
+
+  /**
    * Specify whether all new NumberFormat instances will use latin digits
    * and related characters rather than the localized ones.
    *
@@ -523,70 +601,97 @@
     final String monetarySeparator = remapSeparator(
         orig.monetarySeparator());
     return new NumberConstants() {
+      @Override
       public String currencyPattern() {
         return orig.currencyPattern();
       }
 
+      @Override
       public String decimalPattern() {
         return orig.decimalPattern();
       }
 
+      @Override
       public String decimalSeparator() {
         return decimalSeparator;
       }
 
+      @Override
       public String defCurrencyCode() {
         return orig.defCurrencyCode();
       }
 
+      @Override
       public String exponentialSymbol() {
         return orig.exponentialSymbol();
       }
 
+      @Override
+      public String globalCurrencyPattern() {
+        return orig.globalCurrencyPattern();
+      }
+
+      @Override
       public String groupingSeparator() {
         return groupingSeparator;
       }
 
+      @Override
       public String infinity() {
         return orig.infinity();
       }
 
+      @Override
       public String minusSign() {
         return orig.minusSign();
       }
 
+      @Override
       public String monetaryGroupingSeparator() {
         return monetaryGroupingSeparator;
       }
 
+      @Override
       public String monetarySeparator() {
         return monetarySeparator;
       }
 
+      @Override
       public String notANumber() {
         return orig.notANumber();
       }
 
+      @Override
       public String percent() {
         return orig.percent();
       }
 
+      @Override
       public String percentPattern() {
         return orig.percentPattern();
       }
 
+      @Override
       public String perMill() {
         return orig.perMill();
       }
 
+      @Override
       public String plusSign() {
         return orig.plusSign();
       }
 
+      @Override
       public String scientificPattern() {
         return orig.scientificPattern();
       }
 
+      @Override
+      public String simpleCurrencyPattern() {
+        return orig.simpleCurrencyPattern();
+      }
+
+      @Override
       public String zeroDigit() {
         return "0";
       }
@@ -681,14 +786,15 @@
   }-*/;
 
   /**
-   * The currency code.
+   * Information about the currency being used.
    */
-  private final String currencyCode;
+  private CurrencyData currencyData;
 
   /**
-   * Currency symbol to use.
+   * Holds the current decimal position during one call to
+   * {@link #format(boolean, StringBuilder, int)}.
    */
-  private final String currencySymbol;
+  private transient int decimalPosition;
 
   /**
    * Forces the decimal separator to always appear in a formatted number.
@@ -696,18 +802,30 @@
   private boolean decimalSeparatorAlwaysShown = false;
 
   /**
+   * Holds the current digits length during one call to
+   * {@link #format(boolean, StringBuilder, int)}.
+   */
+  private transient int digitsLength;
+
+  /**
+   * Holds the current exponent during one call to
+   * {@link #format(boolean, StringBuilder, int)}.
+   */
+  private transient int exponent;
+  /**
    * The number of digits between grouping separators in the integer portion of
    * a number.
    */
   private int groupingSize = 3;
-
   private boolean isCurrencyFormat = false;
-
   private int maximumFractionDigits = 3; // invariant, >= minFractionDigits.
 
   private int maximumIntegerDigits = 40;
+
   private int minExponentDigits;
+
   private int minimumFractionDigits = 0;
+
   private int minimumIntegerDigits = 1;
 
   // The multiplier for use in percent, per mille, etc.
@@ -731,24 +849,6 @@
   private boolean useExponentialNotation = false;
 
   /**
-   * Holds the current exponent during one call to
-   * {@link #format(boolean, StringBuilder, int)}.
-   */
-  private transient int exponent;
-
-  /**
-   * Holds the current decimal position during one call to
-   * {@link #format(boolean, StringBuilder, int)}.
-   */
-  private transient int decimalPosition;
-
-  /**
-   * Holds the current digits length during one call to
-   * {@link #format(boolean, StringBuilder, int)}.
-   */
-  private transient int digitsLength;
-
-  /**
    * Constructs a format object based on the specified settings.
    *
    * @param numberConstants the locale-specific number constants to use for this
@@ -767,13 +867,12 @@
     }
     this.numberConstants = numberConstants;
     this.pattern = pattern;
-    currencyCode = cdata.getCurrencyCode();
-    currencySymbol = cdata.getCurrencySymbol();
+    currencyData = cdata;
 
     // TODO: handle per-currency flags, such as symbol prefix/suffix and spacing
     parsePattern(this.pattern);
     if (!userSuppliedPattern && isCurrencyFormat) {
-      minimumFractionDigits = cdata.getDefaultFractionDigits();
+      minimumFractionDigits = currencyData.getDefaultFractionDigits();
       maximumFractionDigits = minimumFractionDigits;
     }
   }
@@ -1368,9 +1467,15 @@
             isCurrencyFormat = true;
             if ((pos + 1) < len && pattern.charAt(pos + 1) == CURRENCY_SIGN) {
               ++pos;
-              affix.append(currencyCode);
+              if (pos < len - 3 && pattern.charAt(pos + 1) == CURRENCY_SIGN
+                  && pattern.charAt(pos + 2) == CURRENCY_SIGN) {
+                pos += 2;
+                affix.append(currencyData.getSimpleCurrencySymbol());
+              } else {
+                affix.append(currencyData.getCurrencyCode());
+              }
             } else {
-              affix.append(currencySymbol);
+              affix.append(currencyData.getCurrencySymbol());
             }
             break;
           case PATTERN_PERCENT:
diff --git a/user/src/com/google/gwt/i18n/client/constants/CurrencyExtra.properties b/user/src/com/google/gwt/i18n/client/constants/CurrencyExtra.properties
index 00e0b1c..35c09a4 100644
--- a/user/src/com/google/gwt/i18n/client/constants/CurrencyExtra.properties
+++ b/user/src/com/google/gwt/i18n/client/constants/CurrencyExtra.properties
@@ -13,7 +13,7 @@
 # the License.
 
 # This file contains additional data about currencies which are not included in
-# the CLDR data.  Currently, this file contains three fields separated by "|".
+# the CLDR data.  Currently, this file contains four fields separated by "|".
 # Empty trailing fields can be omitted along with their separators.
 #
 # The first field is a "portable" currency symbol, which is intended to be
@@ -33,52 +33,160 @@
 #
 # The third field overrides the CLDR-derived currency symbol if present.
 #
+# The fourth field is the simple currency symbol, if present.
+#
 # The following were set to 10 originally, which is POSITION_FLAG without
 # POS_FIXED_FLAG.  As I understand the code, this would have no effect.
 #  CZK DKK EUR ILS ISK NOK RUB SEK
-AED = DH
-ARS = AR$
-AUD = AU$
-BDT = Tk
-BRL = R$
-CAD = C$
-CHF = CHF
-CLP = CL$
-CNY = RMB¥
-COP = COL$
-CRC = CR₡
-CUP = $MN
-CZK = Kč
-DKK = kr
-DOP = RD$
-EGP = LE
-EUR = €
-GBP = GB£
-HKD = HK$
-ILS = IL₪
-INR = Rs
-ISK = kr
-JMD = JA$
-JPY = JP¥
-KRW = KR₩
-LKR = SLRs
-MNT = MN₮
-MXN = Mex$
-MYR = RM
-NOK = NOkr
-PAB = B/.
-PEN = S/.
-PHP = PHP
-PKR = PKRs.
-RUB = руб
-SAR = SR
-SEK = kr
-SGD = S$
-THB = THB
+AED = DH|||dh
+AFN = |||Af.
+ALL = |||Lek
+AMD = |||Dram
+AOA = |||Kz
+ARS = AR$|||$
+AUD = AU$|||$
+AWG = |||Afl.
+AZN = |||man.
+BAM = |||KM
+BBD = |||$
+BDT = Tk|||\u09F3
+BIF = |||FBu
+BGN = |||lev
+BHD = |||din
+BMD = |||$
+BND = |||$
+BOB = |||Bs
+BRL = R$|||R$
+BSD = |||$
+BTN = |||Nu.
+BWP = |||P
+BYR = |||BYR
+BZD = |||$
+CAD = C$|||$
+CDF = |||FrCD
+CHF = CHF|||CHF
+CLP = CL$|||$
+CNY = RMB¥|||¥
+COP = COL$|||$
+CRC = CR₡|||\u20A1
+CUC = |||$
+CUP = $MN|||$
+CVE = |||CVE
+CZK = Kč|||K\u010D
+DJF = Fdj
+DKK = kr|||kr
+DOP = RD$|||$
+DZD = |||din
+EGP = LE|||E£
+ERN = |||Nfk
+ETB = |||Birr
+EUR = €|||\u20AC
+FJD = |||$
+FKP = |||£
+GBP = GB£|||£
+GEL = |||GEL
+GHS = |||GHS
+GIP = |||£
+GMD = |||GMD
+GNF = |||FG
+GTQ = |||Q
+GYD = |||$
+HKD = HK$|||$
+HNL = ||L
+HRK = |||kn
+HTG = |||HTG
+HUF = |||Ft
+IDR = |||Rp
+ILS = IL₪|||\u20AA
+INR = Rs|||\u20B9
+IQD = |||din
+IRR = |||Rial
+ISK = kr|||kr
+JMD = JA$|||$
+JOD = |||din
+JPY = JP¥|||¥
+KES = Ksh
+KGS = |||KGS
+KHR = |||Riel
+KMF = |||CF
+KPW = |||\u20A9
+KRW = KR₩|||\u20A9
+KWD = |||din
+KYD = |||$
+KZT = |||\u20B8
+LAK = |||\u20AD
+LBP = |||L£
+LKR = SLRs|||Rs
+LRD = |||$
+LSL = |||LSL
+LTL = |||Lt
+LVL = |||Ls
+LYD = |||din
+MDL = |||MDL
+MKD = |||dh
+MGA = |||Ar
+MKD = |||din
+MMK = |||K
+MNT = MN₮|||\u20AE
+MOP = |||MOP
+MRO = |||MRO
+MUR = |||Rs
+MWK = |||MWK
+MXN = Mex$|||$
+MYR = RM|||RM
+MZN = |||MTn
+NAD = |||$
+NIO = |||C$
+NGN = |||\u20A6
+NOK = NOkr|||kr
+NPR = |||Rs
+NZD = |||$
+OMR = |||Rial
+PAB = B/.|||B/.
+PEN = S/.|||S/.
+PHP = PHP|||\u20B1
+PKR = PKRs.|||Rs
+PLN = |||z\u0142
+PYG = |||Gs
+QAR = |||Rial
+RON = |||RON
+RSD = |||din
+RUB = руб|||Rup
+RWF = |||RF
+SAR = SR|||Rial
+SBD = |||$
+SCR = |||SCR
+SDG = |||SDG
+SEK = kr|||kr
+SGD = S$|||$
+SHP = |||£
+SLL = |||SLL
+SOS = |||SOS
+SRD = |||$
+STD = |||Db
+SYP = |||£
+SZL = |||SZL
+THB = THB|||\u0E3F
+TJS = |||Som
+TND = |||din
+TOP = |||T$
 TRY = YTL
-TWD = NT$
-USD = US$
-UYU = UY$
-VND = ₫|SymSuffix
-YER = YER
-ZAR = ZAR
+TTD = |||$
+TWD = NT$|||NT$
+TZS = |||TSh
+UAH = |||\u20B4
+UGX = |||UGX
+USD = US$|||$
+UYU = UY$|||$
+UZS = |||so\u02BCm
+VEF = |||Bs
+VND = ₫|SymSuffix||\u20AB
+VUV = |||VUV
+WST = |||WST
+XAF = |||FCFA
+XCD = |||$
+XOF = |||CFA
+XPF = |||FCFP
+YER = YER|||Rial
+ZAR = ZAR|||R
+ZMK = |||ZWK
diff --git a/user/src/com/google/gwt/i18n/client/constants/NumberConstants.java b/user/src/com/google/gwt/i18n/client/constants/NumberConstants.java
index d7c2b8b..aa1a55f 100644
--- a/user/src/com/google/gwt/i18n/client/constants/NumberConstants.java
+++ b/user/src/com/google/gwt/i18n/client/constants/NumberConstants.java
@@ -28,21 +28,23 @@
  * use LocaleInfo.getCurrentLocale().getNumberConstants() instead.
  */
 public interface NumberConstants {
-  String   notANumber();
-  String   currencyPattern();
-  String   decimalPattern();
-  String   decimalSeparator();
-  String   defCurrencyCode();
-  String   exponentialSymbol();
-  String   groupingSeparator();
-  String   infinity();
-  String   minusSign();
-  String   monetaryGroupingSeparator();
-  String   monetarySeparator();
-  String   percent();
-  String   percentPattern();
-  String   perMill();
-  String   plusSign();
-  String   scientificPattern();
-  String   zeroDigit();
+  String notANumber();
+  String currencyPattern();
+  String decimalPattern();
+  String decimalSeparator();
+  String defCurrencyCode();
+  String exponentialSymbol();
+  String globalCurrencyPattern();
+  String groupingSeparator();
+  String infinity();
+  String minusSign();
+  String monetaryGroupingSeparator();
+  String monetarySeparator();
+  String percent();
+  String percentPattern();
+  String perMill();
+  String plusSign();
+  String scientificPattern();
+  String simpleCurrencyPattern();
+  String zeroDigit();
 }
diff --git a/user/src/com/google/gwt/i18n/client/constants/NumberConstantsImpl.java b/user/src/com/google/gwt/i18n/client/constants/NumberConstantsImpl.java
index 2fd1b77..0c5e294 100644
--- a/user/src/com/google/gwt/i18n/client/constants/NumberConstantsImpl.java
+++ b/user/src/com/google/gwt/i18n/client/constants/NumberConstantsImpl.java
@@ -27,21 +27,60 @@
  * locale. 
  */
 public interface NumberConstantsImpl extends Constants, NumberConstants  {
-  String   notANumber();
-  String   currencyPattern();
-  String   decimalPattern();
-  String   decimalSeparator();
-  String   defCurrencyCode();
-  String   exponentialSymbol();
-  String   groupingSeparator();
-  String   infinity();
-  String   minusSign();
-  String   monetaryGroupingSeparator();
-  String   monetarySeparator();
-  String   percent();
-  String   percentPattern();
-  String   perMill();
-  String   plusSign();
-  String   scientificPattern();
-  String   zeroDigit();
+  @Override
+  String notANumber();
+
+  @Override
+  String currencyPattern();
+
+  @Override
+  String decimalPattern();
+
+  @Override
+  String decimalSeparator();
+
+  @Override
+  String defCurrencyCode();
+
+  @Override
+  String exponentialSymbol();
+
+  @Override
+  String globalCurrencyPattern();
+
+  @Override
+  String groupingSeparator();
+
+  @Override
+  String infinity();
+
+  @Override
+  String minusSign();
+
+  @Override
+  String monetaryGroupingSeparator();
+
+  @Override
+  String monetarySeparator();
+
+  @Override
+  String percent();
+
+  @Override
+  String percentPattern();
+
+  @Override
+  String perMill();
+
+  @Override
+  String plusSign();
+
+  @Override
+  String scientificPattern();
+
+  @Override
+  String simpleCurrencyPattern();
+
+  @Override
+  String zeroDigit();
 }
diff --git a/user/src/com/google/gwt/i18n/client/constants/NumberConstantsImpl.properties b/user/src/com/google/gwt/i18n/client/constants/NumberConstantsImpl.properties
index a971da3..e8a9abe 100644
--- a/user/src/com/google/gwt/i18n/client/constants/NumberConstantsImpl.properties
+++ b/user/src/com/google/gwt/i18n/client/constants/NumberConstantsImpl.properties
@@ -1,5 +1,6 @@
 # This file is generated from CLDR ver 1.7.1
 decimalSeparator = .
+globalCurrencyPattern = \u00A4\u00A4\u00A4\u00A4#,##0.00 \u00A4\u00A4;(\u00A4\u00A4\u00A4\u00A4#,##0.00 \u00A4\u00A4)
 groupingSeparator = ,
 percent = %
 zeroDigit = 0
@@ -13,6 +14,7 @@
 monetaryGroupingSeparator = ,
 decimalPattern = #,##0.###
 scientificPattern = #E0
+simpleCurrencyPattern = \u00A4\u00A4\u00A4\u00A4#,##0.00;(\u00A4\u00A4\u00A4\u00A4#,##0.00)
 percentPattern = #,##0%
 currencyPattern = \u00A4#,##0.00;(\u00A4#,##0.00)
 defCurrencyCode = USD
diff --git a/user/src/com/google/gwt/i18n/client/impl/CurrencyDataImpl.java b/user/src/com/google/gwt/i18n/client/impl/CurrencyDataImpl.java
index 92ec8ab..6716e02 100644
--- a/user/src/com/google/gwt/i18n/client/impl/CurrencyDataImpl.java
+++ b/user/src/com/google/gwt/i18n/client/impl/CurrencyDataImpl.java
@@ -71,25 +71,41 @@
   private final int flagsAndPrecision;
 
   /**
-   * Portable currency symbol, may be the same as {@link #currencySymbol}.
+   * Portable currency symbol, may be the same as {@link #getCurrencySymbol()}.
    */
   private final String portableCurrencySymbol;
 
   /**
+   * Simple currency symbol, may be the same as {@link #getCurrencySymbol()}.
+   */
+  private final String simpleCurrencySymbol;
+
+  /**
    * 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) {
+    this(currencyCode, currencySymbol, flagsAndPrecision, null, null);
+  }
+
+  /**
+   * Create a new CurrencyData whose portable symbol is the same as its local
+   * symbol.
+   */
+  public CurrencyDataImpl(String currencyCode, String currencySymbol, int flagsAndPrecision,
+      String portableCurrencySymbol) {
+    this(currencyCode, currencySymbol, flagsAndPrecision, portableCurrencySymbol, null);
   }
 
   public CurrencyDataImpl(String currencyCode, String currencySymbol,
-      int flagsAndPrecision, String portableCurrencySymbol) {
+      int flagsAndPrecision, String portableCurrencySymbol, String simpleCurrencySymbol) {
     super(currencyCode, currencySymbol,
         getDefaultFractionDigits(flagsAndPrecision));
     this.flagsAndPrecision = flagsAndPrecision;
-    this.portableCurrencySymbol = portableCurrencySymbol;
+    this.portableCurrencySymbol = portableCurrencySymbol == null ? currencySymbol
+        : portableCurrencySymbol;
+    this.simpleCurrencySymbol = simpleCurrencySymbol == null ? currencySymbol
+        : simpleCurrencySymbol;
   }
 
   @Override
@@ -103,6 +119,11 @@
   }
 
   @Override
+  public String getSimpleCurrencySymbol() {
+    return simpleCurrencySymbol;
+  }
+
+  @Override
   public boolean isDeprecated() {
     return isDeprecated(flagsAndPrecision);
   }
diff --git a/user/src/com/google/gwt/i18n/client/impl/CurrencyDataJso.java b/user/src/com/google/gwt/i18n/client/impl/CurrencyDataJso.java
index 865335b..8b3ca62 100644
--- a/user/src/com/google/gwt/i18n/client/impl/CurrencyDataJso.java
+++ b/user/src/com/google/gwt/i18n/client/impl/CurrencyDataJso.java
@@ -32,6 +32,7 @@
  *       d5:    space is forced, 0=no space present
  *       d6:    spacing around currency symbol is based on d5
  *   3 - portable currency symbol (optional)
+ *   4 - simple currency symbol (optional)
  * </pre>
  */
 public final class CurrencyDataJso extends JavaScriptObject implements CurrencyData {
@@ -39,38 +40,52 @@
   protected CurrencyDataJso() {
   }
 
+  @Override
   public native String getCurrencyCode() /*-{
     return this[0];
   }-*/;
 
+  @Override
   public native String getCurrencySymbol() /*-{
     return this[1];
   }-*/;
 
+  @Override
   public int getDefaultFractionDigits() {
     return CurrencyDataImpl.getDefaultFractionDigits(getFlagsAndPrecision());
   }
 
+  @Override
   public native String getPortableCurrencySymbol() /*-{
     return this[3] || this[1];
   }-*/;
 
+  @Override
+  public native String getSimpleCurrencySymbol() /*-{
+    return this[4] || this[1];
+  }-*/;
+
+  @Override
   public boolean isDeprecated() {
     return CurrencyDataImpl.isDeprecated(getFlagsAndPrecision());
   }
 
+  @Override
   public boolean isSpaceForced() {
     return CurrencyDataImpl.isSpaceForced(getFlagsAndPrecision());
   }
 
+  @Override
   public boolean isSpacingFixed() {
     return CurrencyDataImpl.isSpacingFixed(getFlagsAndPrecision());
   }
 
+  @Override
   public boolean isSymbolPositionFixed() {
     return CurrencyDataImpl.isSymbolPositionFixed(getFlagsAndPrecision());
   }
 
+  @Override
   public boolean isSymbolPrefix() {
     return CurrencyDataImpl.isSymbolPrefix(getFlagsAndPrecision());
   }
diff --git a/user/src/com/google/gwt/i18n/rebind/CurrencyListGenerator.java b/user/src/com/google/gwt/i18n/rebind/CurrencyListGenerator.java
index a6a9cef..214e1bb 100644
--- a/user/src/com/google/gwt/i18n/rebind/CurrencyListGenerator.java
+++ b/user/src/com/google/gwt/i18n/rebind/CurrencyListGenerator.java
@@ -74,6 +74,8 @@
 
     private final String symbol;
 
+    private String simpleSymbol;
+
     /**
      * Create an instance.
      * 
@@ -123,6 +125,7 @@
       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];
       }
@@ -145,6 +148,7 @@
         // 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) {
@@ -166,6 +170,11 @@
         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) {
@@ -176,10 +185,17 @@
       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;
     }
 
@@ -187,17 +203,12 @@
       return displayName;
     }
 
-    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('\"');
-      }
+      buf.append(", \"").append(quote(portableSymbol)).append('\"');
+      buf.append(", \"").append(quote(simpleSymbol)).append('\"');
       return buf.append(')').toString();
     }
 
@@ -205,19 +216,10 @@
       StringBuilder buf = new StringBuilder();
       buf.append("[ \"").append(quote(code)).append("\", \"");
       buf.append(quote(symbol)).append("\", ").append(flags);
-      if (portableSymbol.length() > 0) {
-        buf.append(", \"").append(quote(portableSymbol)).append('\"');
-      }
+      buf.append(", \"").append(quote(portableSymbol)).append('\"');
+      buf.append(", \"").append(quote(simpleSymbol)).append('\"');
       return buf.append(']').toString();
     }
-
-    public String getSymbol() {
-      return symbol;
-    }
-
-    public boolean isObsolete() {
-      return obsolete;
-    }
   }
 
   private static final String CURRENCY_DATA = CurrencyDataImpl.class.getCanonicalName();
@@ -667,12 +669,11 @@
    * 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
+   * @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<String, CurrencyInfo> allCurrencyData) {
@@ -707,12 +708,11 @@
    * 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
+   * @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<String, CurrencyInfo> allCurrencyData) {
@@ -754,10 +754,11 @@
    * 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
+   * @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) {
@@ -793,10 +794,11 @@
    * 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
+   * @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) {
diff --git a/user/test/com/google/gwt/i18n/client/NumberFormat_en_Test.java b/user/test/com/google/gwt/i18n/client/NumberFormat_en_Test.java
index 3769508..f69c5cd 100644
--- a/user/test/com/google/gwt/i18n/client/NumberFormat_en_Test.java
+++ b/user/test/com/google/gwt/i18n/client/NumberFormat_en_Test.java
@@ -124,6 +124,34 @@
     formatter = NumberFormat.getCurrencyFormat("ITL");
     str = formatter.format(1234.556);
     assertEquals("IT₤1,235", str);
+
+    // Test simple currency formatting
+    str = NumberFormat.getSimpleCurrencyFormat().format(1234.75);
+    assertEquals("$1,234.75", str);
+    str = NumberFormat.getSimpleCurrencyFormat().format(-1234.75);
+    assertEquals("($1,234.75)", str);
+    str = NumberFormat.getSimpleCurrencyFormat("CAD").format(1234.75);
+    assertEquals("$1,234.75", str);
+    str = NumberFormat.getSimpleCurrencyFormat("AUD").format(1234.75);
+    assertEquals("$1,234.75", str);
+    str = NumberFormat.getSimpleCurrencyFormat("JPY").format(1234.75);
+    assertEquals("¥1,235", str);
+    str = NumberFormat.getSimpleCurrencyFormat("CNY").format(1234.75);
+    assertEquals("¥1,234.75", str);
+
+    // Test global currency formatting
+    str = NumberFormat.getGlobalCurrencyFormat().format(1234.75);
+    assertEquals("$1,234.75 USD", str);
+    str = NumberFormat.getGlobalCurrencyFormat().format(-1234.75);
+    assertEquals("($1,234.75 USD)", str);
+    str = NumberFormat.getGlobalCurrencyFormat("CAD").format(1234.75);
+    assertEquals("$1,234.75 CAD", str);
+    str = NumberFormat.getGlobalCurrencyFormat("AUD").format(1234.75);
+    assertEquals("$1,234.75 AUD", str);
+    str = NumberFormat.getGlobalCurrencyFormat("JPY").format(1234.75);
+    assertEquals("¥1,235 JPY", str);
+    str = NumberFormat.getGlobalCurrencyFormat("CNY").format(1234.75);
+    assertEquals("¥1,234.75 CNY", str);
   }
 
   public void testExponential() {