View Javadoc

1   /*
2    * $Id: PatchedNumberConverter.java,v 1.18 2011/06/16 09:29:40 jbmeslin Exp $
3    * 
4    */
5   package org.rcfaces.core.internal.converter;
6   
7   import java.text.DecimalFormat;
8   import java.text.DecimalFormatSymbols;
9   import java.text.NumberFormat;
10  import java.text.ParseException;
11  import java.util.Currency;
12  import java.util.Locale;
13  
14  import javax.faces.component.UIComponent;
15  import javax.faces.context.FacesContext;
16  import javax.faces.convert.ConverterException;
17  import javax.faces.convert.NumberConverter;
18  
19  /**
20   * 
21   * @author Olivier Oeuillot (latest modification by $Author: jbmeslin $)
22   * @version $Revision: 1.18 $ $Date: 2011/06/16 09:29:40 $
23   */
24  public class PatchedNumberConverter extends NumberConverter {
25      private static final String REVISION = "$Revision: 1.18 $";
26  
27      private static final boolean ENABLE_PATCHED_NUMBER_CONVERTER = true;
28  
29      private Locale locale;
30  
31      public Object getAsObject(FacesContext context, UIComponent component,
32              String value) {
33          if (ENABLE_PATCHED_NUMBER_CONVERTER == false) {
34              return super.getAsObject(context, component, value);
35          }
36  
37          if (context == null || component == null) {
38              throw new NullPointerException();
39          }
40  
41          try {
42  
43              // If the specified value is null or zero-length, return null
44              if (value == null) {
45                  return (null);
46              }
47              value = value.trim();
48              if (value.length() < 1) {
49                  return (null);
50              }
51  
52              // Identify the Locale to use for parsing
53              Locale locale = getLocale(context);
54  
55              // Create and configure the parser to be used
56              NumberFormat parser = getNumberFormat(locale);
57              parser.setParseIntegerOnly(isIntegerOnly());
58  
59              String pattern = getPattern();
60              String type = getType();
61  
62              if (((pattern != null) && !pattern.equals(""))
63                      || "currency".equals(type)) {
64                  configureCurrency(parser);
65              }
66              configureFormatter(parser);
67  
68              // Perform the requested parsing
69              return (parser.parse(value));
70  
71          } catch (ConverterException e) {
72              throw e;
73          } catch (ParseException e) {
74              // PENDING(craigmcc) - i18n
75              throw new ConverterException("Error parsing '" + value + "'");
76          }
77  
78      }
79  
80      private void configureFormatter(NumberFormat formatter) {
81  
82          boolean groupingUsed = isGroupingUsed();
83  
84          formatter.setGroupingUsed(groupingUsed);
85      }
86  
87      private Locale getLocale(FacesContext context) {
88  
89          // PENDING(craigmcc) - JSTL localization context?
90          Locale locale = this.locale;
91          if (locale == null) {
92              locale = context.getViewRoot().getLocale();
93          }
94          return (locale);
95  
96      }
97  
98      private NumberFormat getNumberFormat(Locale locale) {
99  
100         String pattern = getPattern();
101         String type = getType();
102 
103         if (pattern == null && type == null) {
104             throw new IllegalArgumentException("Either pattern or type must"
105                     + " be specified.");
106         }
107 
108         // PENDING(craigmcc) - Implement pooling if needed for performance?
109 
110         // If pattern is specified, type is ignored
111         if (pattern != null) {
112             DecimalFormatSymbols symbols = new DecimalFormatSymbols(locale);
113             return (new DecimalFormat(pattern, symbols));
114         }
115 
116         // Create an instance based on the specified type
117         else if (type.equals("currency")) {
118             return (NumberFormat.getCurrencyInstance(locale));
119         } else if (type.equals("number")) {
120             return (NumberFormat.getNumberInstance(locale));
121         } else if (type.equals("percent")) {
122             return (NumberFormat.getPercentInstance(locale));
123         } else {
124             // PENDING(craigmcc) - i18n
125             throw new ConverterException(new IllegalArgumentException(type));
126         }
127 
128     }
129 
130     private void configureCurrency(NumberFormat formatter) {
131 
132         // Implementation copied from JSTL's FormatNumberSupport.setCurrency()
133 
134         String code = null;
135         String symbol = null;
136 
137         String currencyCode = getCurrencyCode();
138         String currencySymbol = getCurrencySymbol();
139 
140         if ((currencyCode == null) && (currencySymbol == null)) {
141             return;
142         }
143 
144         if ((currencyCode != null) && (currencySymbol != null)) {
145             code = currencyCode;
146         } else if (currencyCode == null) {
147             symbol = currencySymbol;
148         } else {
149             code = currencyCode;
150         }
151 
152         DecimalFormat df = (DecimalFormat) formatter;
153 
154         DecimalFormatSymbols dfs;
155         boolean symbolsModified = false;
156         if (code != null) {
157             Currency currency = Currency.getInstance(code);
158 
159             formatter.setCurrency(currency);
160 
161             dfs = df.getDecimalFormatSymbols();
162         } else {
163             dfs = df.getDecimalFormatSymbols();
164 
165             dfs.setCurrencySymbol(symbol);
166             symbolsModified = true;
167         }
168 
169         char cs = dfs.getGroupingSeparator();
170         // Traitement du Non breaking space !
171         if (cs == '\u00A0') {
172             dfs.setGroupingSeparator(' ');
173             symbolsModified = true;
174         }
175 
176         if (symbolsModified) {
177             df.setDecimalFormatSymbols(dfs);
178         }
179     }
180 
181 }