You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by gc...@apache.org on 2009/01/31 01:10:00 UTC

svn commit: r739455 - in /myfaces/trinidad/trunk: trinidad-api/src/main/java/org/apache/myfaces/trinidad/convert/NumberConverter.java trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/convert/NumberConverter.java

Author: gcrawford
Date: Sat Jan 31 00:10:00 2009
New Revision: 739455

URL: http://svn.apache.org/viewvc?rev=739455&view=rev
Log:
TRINIDAD-1374 NumberConverter with type='number' and pattern set gives malformed error

Modified:
    myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/convert/NumberConverter.java
    myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/convert/NumberConverter.java

Modified: myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/convert/NumberConverter.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/convert/NumberConverter.java?rev=739455&r1=739454&r2=739455&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/convert/NumberConverter.java (original)
+++ myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/convert/NumberConverter.java Sat Jan 31 00:10:00 2009
@@ -28,6 +28,8 @@
 import java.util.Locale;
 import java.util.Map;
 
+import java.util.regex.Matcher;
+
 import javax.faces.application.FacesMessage;
 import javax.faces.component.UIComponent;
 import javax.faces.context.FacesContext;
@@ -254,7 +256,7 @@
       // be able to parse 'value' as a Number.
       // An error occured, so the index of pp should still be 0.
       num = (Number)nfmt.parseObject(value, pp);      
-      if("percent".equals(type) && num != null)
+      if (typeIdx == _PERCENT_TYPE && num != null)
         num = num.doubleValue() / 100.0;
     }
     
@@ -268,25 +270,39 @@
 
     if (pp.getIndex() != value.length())
     {
+      // According to the comments in 
+      // trinidad-api\src\main\xrts\org\apache\myfaces\trinidad\resource\MessageBundle.xrts,
+      // the substitution parameters are supposed to be:
+      // {0} the label that identifies the component
+      // {1} value entered by the user
       Object label = ConverterUtils.getComponentLabel(component);
       Object[] params = null;
-      if("currency".equals(type))
+      
+      if (typeIdx == _PATTERN_TYPE)
       {
-        params = new Object[] {label, getPattern(), fmt.format(_EXAMPLE_CURRENCY)};
+        // We call this since the pattern may contain the generic currency sign '¤', which we don't 
+        // want to display to the user.
+        pattern = getLocalizedPattern(context, pattern, dfs);
+        
+        params = new Object[] {label, value, pattern};
       }
-      else if("percent".equals(type))
+      else if (typeIdx == _NUMBER_TYPE)
       {
-        params = new Object[] {label, getPattern(), fmt.format(_EXAMPLE_PERCENT)};
+        params = new Object[] {label, value};
       }
-      else
+      else if (typeIdx == _CURRENCY_TYPE)
       {
-        params = new Object[] {label, getPattern()};
+        params = new Object[] {label, value, fmt.format(_EXAMPLE_CURRENCY)};
+      }
+      else if (typeIdx == _PERCENT_TYPE)
+      {
+        params = new Object[] {label, value, fmt.format(_EXAMPLE_PERCENT)};
       }
-        
         
       throw new ConverterException(
         getConvertMessage(context, component, value, params));
     }
+
     // if we set setParseIntegerOnly(isIntegerOnly()) - This may result in
     // the formatter stopping to parse after the first decimal point.
     // that is number of value 222.22 which is legitimate, hence our test would
@@ -299,7 +315,6 @@
       return Long.valueOf(num.longValue());
 
     return num;
-
   }
 
   /**
@@ -694,6 +709,59 @@
     return ComponentUtils.resolveString(pattern);
   }
 
+  /**
+   * If <code>pattern</code> contains the generic currency sign '¤', this method will replace it 
+   * with the localized currency symbol (if one exists). 
+   * @param context the FacesContext
+   * @param pattern the pattern to be localized
+   * @param dfs the DecimalFormatSymbols; if null, will be constructed from the <code>context</code>
+   * @return
+   */
+  public String getLocalizedPattern(FacesContext context, String pattern, DecimalFormatSymbols dfs)
+  {
+    if (pattern == null)
+      return null;
+    
+    // If the pattern contains the generic currency sign '¤', replace it with the localized 
+    // currency symbol (if one exists), so that when the pattern is displayed (such as in an error 
+    // message), it is more meaningful to the user.
+    // If the pattern contains '¤¤', replace it with the international currency symbol. 
+    // For an explanation of this behavior, see section "Special Pattern Characters" at: 
+    // http://java.sun.com/javase/6/docs/api/java/text/DecimalFormat.html
+    // The unicode for '¤' is: \u00A4
+    // The xml hex is        : &#xA4;
+    int idx = pattern.indexOf("¤");
+    if (idx == -1)
+      return pattern;
+    
+    if (dfs == null)
+    {
+      String type = getType();
+      RequestContext reqCtx = RequestContext.getCurrentInstance();
+      Locale locale = _getLocale(reqCtx, context);
+      NumberFormat fmt = _getNumberFormat(pattern, type, locale, reqCtx);
+      DecimalFormat df = (DecimalFormat) fmt;
+      dfs = df.getDecimalFormatSymbols();
+    }
+    
+    if (idx + 1 < pattern.length() && pattern.charAt(idx + 1) == '¤')
+    {
+      // Matcher.quoteReplacement ensures that the replacement string is properly escaped.
+      String symbol = dfs.getInternationalCurrencySymbol();
+      if (symbol.length() > 0)
+        pattern = pattern.replaceFirst("¤¤", Matcher.quoteReplacement(symbol));
+    }
+    else
+    {
+      // Matcher.quoteReplacement ensures that the replacement string is properly escaped.
+      String symbol = dfs.getCurrencySymbol();
+      if (symbol.length() > 0)
+        pattern = pattern.replaceFirst("¤", Matcher.quoteReplacement(symbol));
+    }
+    
+    return pattern;
+  }
+
   @Override
   public void setType(String type)
   {

Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/convert/NumberConverter.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/convert/NumberConverter.java?rev=739455&r1=739454&r2=739455&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/convert/NumberConverter.java (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/convert/NumberConverter.java Sat Jan 31 00:10:00 2009
@@ -118,7 +118,7 @@
    * formatted numbers, like currencyCode or maximumIntegerDigits.
    * 
    */
-  private Object[] _getClientConstructorParams(Map<?, ?> messages)
+  private Object[] _getClientConstructorParams(FacesContext context, Map<?, ?> messages)
   {
     Object[] params;
     boolean formating = _formatingAttributesSet();
@@ -127,7 +127,11 @@
       params = new Object[12];
     else
       params = new Object[4];
-    params[0] = this.getPattern();
+
+    // We call this since the pattern may contain the generic currency sign '¤', which we don't 
+    // want to display to the user.
+    params[0] = getLocalizedPattern(context, getPattern(), null);
+
     params[1] = this.getType();
     params[2] = this.getLocale() != null ? this.getLocale().toString() : null;
     params[3] = messages;
@@ -184,7 +188,7 @@
       else
       {
 
-        Object[] params = _getClientConstructorParams(messages);
+        Object[] params = _getClientConstructorParams(context, messages);
         
         outBuffer.append("new TrNumberConverter(");
 
@@ -205,4 +209,4 @@
       return outBuffer.toString();
     }
   private static final Collection<String> _IMPORT_NAMES = Collections.singletonList( "TrNumberConverter()" );
-}
\ No newline at end of file
+}