1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package javax.faces.convert;
20
21 import javax.faces.component.UIComponent;
22 import javax.faces.component.StateHolder;
23 import javax.faces.context.FacesContext;
24 import java.text.DecimalFormat;
25 import java.text.DecimalFormatSymbols;
26 import java.text.NumberFormat;
27 import java.text.ParseException;
28 import java.util.Currency;
29 import java.util.Locale;
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 public class NumberConverter
48 implements Converter, StateHolder
49 {
50
51 public static final String CONVERTER_ID = "javax.faces.Number";
52
53
54 private static final String CONVERSION_MESSAGE_ID = "javax.faces.convert.NumberConverter.CONVERSION";
55
56
57 private static final boolean JAVA_VERSION_14;
58
59 static
60 {
61 JAVA_VERSION_14 = checkJavaVersion14();
62 }
63
64 private String _currencyCode;
65 private String _currencySymbol;
66 private Locale _locale;
67 private int _maxFractionDigits;
68 private int _maxIntegerDigits;
69 private int _minFractionDigits;
70 private int _minIntegerDigits;
71 private String _pattern;
72 private String _type = "number";
73 private boolean _groupingUsed = true;
74 private boolean _integerOnly = false;
75 private boolean _transient;
76
77 private boolean _maxFractionDigitsSet;
78 private boolean _maxIntegerDigitsSet;
79 private boolean _minFractionDigitsSet;
80 private boolean _minIntegerDigitsSet;
81
82
83
84 public NumberConverter()
85 {
86 }
87
88
89 public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String value)
90 {
91 if (facesContext == null) throw new NullPointerException("facesContext");
92 if (uiComponent == null) throw new NullPointerException("uiComponent");
93
94 if (value != null)
95 {
96 value = value.trim();
97 if (value.length() > 0)
98 {
99 NumberFormat format = getNumberFormat(facesContext);
100 format.setParseIntegerOnly(_integerOnly);
101
102 DecimalFormat df = (DecimalFormat)format;
103
104 DecimalFormatSymbols dfs = df.getDecimalFormatSymbols();
105 boolean changed = false;
106 if(dfs.getGroupingSeparator() == '\u00a0')
107 {
108 dfs.setGroupingSeparator(' ');
109 df.setDecimalFormatSymbols(dfs);
110 changed = true;
111 }
112
113 formatCurrency(format);
114
115 try
116 {
117 return format.parse(value);
118 }
119 catch (ParseException e)
120 {
121 if(changed)
122 {
123 dfs.setGroupingSeparator('\u00a0');
124 df.setDecimalFormatSymbols(dfs);
125 }
126 try
127 {
128 return format.parse(value);
129 }
130 catch (ParseException pe)
131 {
132
133 throw new ConverterException(_MessageUtils.getErrorMessage(facesContext,
134 CONVERSION_MESSAGE_ID,
135 new Object[]{uiComponent.getId(),value}), e);
136
137 }
138 }
139 }
140 }
141 return null;
142 }
143
144 public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object value)
145 {
146 if (facesContext == null) throw new NullPointerException("facesContext");
147 if (uiComponent == null) throw new NullPointerException("uiComponent");
148
149 if (value == null)
150 {
151 return "";
152 }
153 if (value instanceof String)
154 {
155 return (String)value;
156 }
157
158 NumberFormat format = getNumberFormat(facesContext);
159 format.setGroupingUsed(_groupingUsed);
160 if (_maxFractionDigitsSet) format.setMaximumFractionDigits(_maxFractionDigits);
161 if (_maxIntegerDigitsSet) format.setMaximumIntegerDigits(_maxIntegerDigits);
162 if (_minFractionDigitsSet) format.setMinimumFractionDigits(_minFractionDigits);
163 if (_minIntegerDigitsSet) format.setMinimumIntegerDigits(_minIntegerDigits);
164 formatCurrency(format);
165 try
166 {
167 return format.format(value);
168 }
169 catch (Exception e)
170 {
171 throw new ConverterException("Cannot convert value '" + value + "'");
172 }
173 }
174
175 private NumberFormat getNumberFormat(FacesContext facesContext)
176 {
177 Locale locale = _locale != null ? _locale : facesContext.getViewRoot().getLocale();
178
179 if (_pattern == null && _type == null)
180 {
181 throw new ConverterException("Cannot get NumberFormat, either type or pattern needed.");
182 }
183
184
185 if (_pattern != null)
186 {
187 return new DecimalFormat(_pattern, new DecimalFormatSymbols(locale));
188 }
189
190
191 if (_type.equals("number"))
192 {
193 return NumberFormat.getNumberInstance(locale);
194 }
195 else if (_type.equals("currency"))
196 {
197 return NumberFormat.getCurrencyInstance(locale);
198 }
199 else if (_type.equals("percent"))
200 {
201 return NumberFormat.getPercentInstance(locale);
202 }
203 throw new ConverterException("Cannot get NumberFormat, illegal type " + _type);
204 }
205
206 private void formatCurrency(NumberFormat format)
207 {
208 if (_currencyCode == null && _currencySymbol == null)
209 {
210 return;
211 }
212
213 boolean useCurrencyCode;
214 if (JAVA_VERSION_14)
215 {
216 useCurrencyCode = _currencyCode != null;
217 }
218 else
219 {
220 useCurrencyCode = _currencySymbol == null;
221 }
222
223 if (useCurrencyCode)
224 {
225
226 try
227 {
228 format.setCurrency(Currency.getInstance(_currencyCode));
229 }
230 catch (Exception e)
231 {
232 throw new ConverterException("Unable to get Currency instance for currencyCode " +
233 _currencyCode);
234 }
235 }
236 else if (format instanceof DecimalFormat)
237
238 {
239 DecimalFormat dFormat = (DecimalFormat)format;
240 DecimalFormatSymbols symbols = dFormat.getDecimalFormatSymbols();
241 symbols.setCurrencySymbol(_currencySymbol);
242 dFormat.setDecimalFormatSymbols(symbols);
243 }
244 }
245
246
247 public void restoreState(FacesContext facesContext, Object state)
248 {
249 Object values[] = (Object[])state;
250 _currencyCode = (String)values[0];
251 _currencySymbol = (String)values[1];
252 _locale = (Locale)values[2];
253 Integer value = (Integer)values[3];
254 _maxFractionDigits = value != null ? value.intValue() : 0;
255 value = (Integer)values[4];
256 _maxIntegerDigits = value != null ? value.intValue() : 0;
257 value = (Integer)values[5];
258 _minFractionDigits = value != null ? value.intValue() : 0;
259 value = (Integer)values[6];
260 _minIntegerDigits = value != null ? value.intValue() : 0;
261 _pattern = (String)values[7];
262 _type = (String)values[8];
263 _groupingUsed = ((Boolean)values[9]).booleanValue();
264 _integerOnly = ((Boolean)values[10]).booleanValue();
265 _maxFractionDigitsSet = ((Boolean)values[11]).booleanValue();
266 _maxIntegerDigitsSet = ((Boolean)values[12]).booleanValue();
267 _minFractionDigitsSet = ((Boolean)values[13]).booleanValue();
268 _minIntegerDigitsSet = ((Boolean)values[14]).booleanValue();
269 }
270
271 public Object saveState(FacesContext facesContext)
272 {
273 Object values[] = new Object[15];
274 values[0] = _currencyCode;
275 values[1] = _currencySymbol;
276 values[2] = _locale;
277 values[3] = _maxFractionDigitsSet ? new Integer(_maxFractionDigits) : null;
278 values[4] = _maxIntegerDigitsSet ? new Integer(_maxIntegerDigits) : null;
279 values[5] = _minFractionDigitsSet ? new Integer(_minFractionDigits) : null;
280 values[6] = _minIntegerDigitsSet ? new Integer(_minIntegerDigits) : null;
281 values[7] = _pattern;
282 values[8] = _type;
283 values[9] = _groupingUsed ? Boolean.TRUE : Boolean.FALSE;
284 values[10] = _integerOnly ? Boolean.TRUE : Boolean.FALSE;
285 values[11] = _maxFractionDigitsSet ? Boolean.TRUE : Boolean.FALSE;
286 values[12] = _maxIntegerDigitsSet ? Boolean.TRUE : Boolean.FALSE;
287 values[13] = _minFractionDigitsSet ? Boolean.TRUE : Boolean.FALSE;
288 values[14] = _minIntegerDigitsSet ? Boolean.TRUE : Boolean.FALSE;
289 return values;
290 }
291
292
293
294
295
296
297
298
299 public String getCurrencyCode()
300 {
301 return _currencyCode != null ?
302 _currencyCode :
303 getDecimalFormatSymbols().getInternationalCurrencySymbol();
304 }
305
306 public void setCurrencyCode(String currencyCode)
307 {
308 _currencyCode = currencyCode;
309 }
310
311
312
313
314
315
316
317 public String getCurrencySymbol()
318 {
319 return _currencySymbol != null ?
320 _currencySymbol :
321 getDecimalFormatSymbols().getCurrencySymbol();
322 }
323
324 public void setCurrencySymbol(String currencySymbol)
325 {
326 _currencySymbol = currencySymbol;
327 }
328
329
330
331
332
333
334 public boolean isGroupingUsed()
335 {
336 return _groupingUsed;
337 }
338
339 public void setGroupingUsed(boolean groupingUsed)
340 {
341 _groupingUsed = groupingUsed;
342 }
343
344
345
346
347
348
349 public boolean isIntegerOnly()
350 {
351 return _integerOnly;
352 }
353
354 public void setIntegerOnly(boolean integerOnly)
355 {
356 _integerOnly = integerOnly;
357 }
358
359
360
361
362
363
364
365 public Locale getLocale()
366 {
367 if (_locale != null) return _locale;
368 FacesContext context = FacesContext.getCurrentInstance();
369 return context.getViewRoot().getLocale();
370 }
371
372 public void setLocale(Locale locale)
373 {
374 _locale = locale;
375 }
376
377
378
379
380
381
382 public int getMaxFractionDigits()
383 {
384 return _maxFractionDigits;
385 }
386
387 public void setMaxFractionDigits(int maxFractionDigits)
388 {
389 _maxFractionDigitsSet = true;
390 _maxFractionDigits = maxFractionDigits;
391 }
392
393
394
395
396
397
398 public int getMaxIntegerDigits()
399 {
400 return _maxIntegerDigits;
401 }
402
403 public void setMaxIntegerDigits(int maxIntegerDigits)
404 {
405 _maxIntegerDigitsSet = true;
406 _maxIntegerDigits = maxIntegerDigits;
407 }
408
409
410
411
412
413
414 public int getMinFractionDigits()
415 {
416 return _minFractionDigits;
417 }
418
419 public void setMinFractionDigits(int minFractionDigits)
420 {
421 _minFractionDigitsSet = true;
422 _minFractionDigits = minFractionDigits;
423 }
424
425
426
427
428
429
430 public int getMinIntegerDigits()
431 {
432 return _minIntegerDigits;
433 }
434
435 public void setMinIntegerDigits(int minIntegerDigits)
436 {
437 _minIntegerDigitsSet = true;
438 _minIntegerDigits = minIntegerDigits;
439 }
440
441
442
443
444
445
446 public String getPattern()
447 {
448 return _pattern;
449 }
450
451 public void setPattern(String pattern)
452 {
453 _pattern = pattern;
454 }
455
456 public boolean isTransient()
457 {
458 return _transient;
459 }
460
461 public void setTransient(boolean aTransient)
462 {
463 _transient = aTransient;
464 }
465
466
467
468
469
470
471
472 public String getType()
473 {
474 return _type;
475 }
476
477 public void setType(String type)
478 {
479
480 _type = type;
481 }
482
483 private static boolean checkJavaVersion14()
484 {
485 String version = System.getProperty("java.version");
486 if (version == null)
487 {
488 return false;
489 }
490 byte java14 = 0;
491 for (int idx = version.indexOf('.'), i = 0; idx > 0 || version != null; i++)
492 {
493 if (idx > 0)
494 {
495 byte value = Byte.parseByte(version.substring(0, 1));
496 version = version.substring(idx + 1, version.length());
497 idx = version.indexOf('.');
498 switch (i)
499 {
500 case 0:
501 if (value == 1)
502 {
503 java14 = 1;
504 break;
505 }
506 else if (value > 1)
507 {
508 java14 = 2;
509 }
510 case 1:
511 if (java14 > 0 && value >= 4)
512 {
513 java14 = 2;
514 }
515 ;
516 default:
517 idx = 0;
518 version = null;
519 break;
520 }
521 }
522 else
523 {
524 byte value = Byte.parseByte(version.substring(0, 1));
525 if (java14 > 0 && value >= 4)
526 {
527 java14 = 2;
528 }
529 break;
530 }
531 }
532 return java14 == 2;
533 }
534
535
536 private DecimalFormatSymbols getDecimalFormatSymbols()
537 {
538 return new DecimalFormatSymbols(getLocale());
539 }
540 }