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