1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.trinidad.validator;
20
21 import javax.el.ValueExpression;
22
23 import javax.faces.application.FacesMessage;
24 import javax.faces.component.UIComponent;
25 import javax.faces.context.FacesContext;
26 import javax.faces.el.ValueBinding;
27
28
29 import javax.faces.validator.Validator;
30 import javax.faces.validator.ValidatorException;
31
32 import org.apache.myfaces.trinidad.bean.FacesBean;
33 import org.apache.myfaces.trinidad.bean.PropertyKey;
34 import org.apache.myfaces.trinidad.util.ComponentUtils;
35 import org.apache.myfaces.trinidad.util.IntegerUtils;
36 import org.apache.myfaces.trinidad.util.MessageFactory;
37
38 /**
39 * <p>Implementation for <code>java.lang.Long</code> values.</p>
40 *
41 */
42 public class LongRangeValidator extends javax.faces.validator.LongRangeValidator
43 {
44
45 public static final String VALIDATOR_ID = "org.apache.myfaces.trinidad.LongRange";
46
47 /**
48 * <p>The message identifier of the {@link javax.faces.application.FacesMessage}
49 * to be created if the maximum value check fails. The message format
50 * string for this message may optionally include <code>{0}</code>,
51 * <code>{1}</code> and <code>{3}</code> placeholders,
52 * which will be replaced by user input, component label and configured
53 * maximum value.</p>
54 */
55 public static final String MAXIMUM_MESSAGE_ID =
56 "org.apache.myfaces.trinidad.validator.LongRangeValidator.MAXIMUM";
57
58 /**
59 * <p>The message identifier of the {@link javax.faces.application.FacesMessage}
60 * to be created if the minimum value check fails. The message format
61 * string for this message may optionally include <code>{0}</code>,
62 * <code>{1}</code> and <code>{2}</code> placeholders, which will be replaced
63 * by user input, component label and configured minimum value.</p>
64 */
65 public static final String MINIMUM_MESSAGE_ID =
66 "org.apache.myfaces.trinidad.validator.LongRangeValidator.MINIMUM";
67
68
69 /**
70 * <p>The message identifier of the {@link javax.faces.application.FacesMessage}
71 * to be created if the maximum or minimum value check fails, and both
72 * the maximum and minimum values for this validator have been set.
73 * The message format string for this message may optionally include
74 * <code>{0}</code>, <code>{1}</code>, <code>{2}</code> and <code>{3}</code>
75 * placeholders, which will be replaced by user input, component label,
76 * configured minimum value and configured maximum value.</p>
77 */
78 public static final String NOT_IN_RANGE_MESSAGE_ID =
79 "org.apache.myfaces.trinidad.validator.LongRangeValidator.NOT_IN_RANGE";
80
81 /**
82 * <p>The message identifier of the FacesMessage to be created if
83 * the value cannot be converted to an integer
84 */
85 public static final String CONVERT_MESSAGE_ID =
86 "org.apache.myfaces.trinidad.convert.LongConverter.CONVERT";
87
88
89 /**
90 * Construct a {@link Validator} with no preconfigured limits.
91 */
92 public LongRangeValidator()
93 {
94 super();
95 }
96
97 /**
98 * Construct a {@link Validator} with the specified preconfigured
99 * limit.
100 *
101 * @param maximum Maximum value to allow
102 */
103 public LongRangeValidator(long maximum)
104 {
105 super(maximum);
106 }
107
108 /**
109 * Construct a {@link Validator} with the specified preconfigured
110 * limits.
111 *
112 * @param maximum Maximum value to allow
113 * @param minimum Minimum value to allow
114 *
115 */
116 public LongRangeValidator(long maximum, long minimum)
117 {
118 super(maximum, minimum);
119 }
120
121 /**
122 * Return the maximum value to be enforced by this {@link
123 * Validator} or null if it has not been
124 * set.
125 */
126 @Override
127 public long getMaximum()
128 {
129 Object maxLong = _facesBean.getProperty(_MAXIMUM_KEY);
130 if(maxLong == null)
131 maxLong = _MAXIMUM_KEY.getDefault();
132 return ComponentUtils.resolveLong(maxLong);
133 }
134
135 /**
136 * Set the maximum value to be enforced by this {@link Validator}.
137 *
138 * @param maximum The new maximum value
139 *
140 */
141 @Override
142 public void setMaximum(long maximum)
143 {
144 _facesBean.setProperty(_MAXIMUM_KEY, Long.valueOf(maximum));
145 }
146
147
148 /**
149 * Return the minimum value to be enforced by this {@link
150 * Validator}, or null if it has not been
151 * set.
152 */
153 @Override
154 public long getMinimum()
155 {
156 Object minLong = _facesBean.getProperty(_MINIMUM_KEY);
157 if(minLong == null)
158 minLong = _MINIMUM_KEY.getDefault();
159 return ComponentUtils.resolveLong(minLong);
160 }
161
162 /**
163 * Set the minimum value to be enforced by this {@link Validator}.
164 *
165 * @param minimum The new minimum value
166 *
167 */
168 @Override
169 public void setMinimum(long minimum)
170 {
171 _facesBean.setProperty(_MINIMUM_KEY, Long.valueOf(minimum));
172 }
173
174 /**
175 * <p>Custom error message to be used, for creating detail part of the
176 * {@link FacesMessage}, when input value exceeds the maximum value set.</p>
177 * Overrides detail message identified by message id {@link #MAXIMUM_MESSAGE_ID}
178 * @param maximumMessageDetail Custom error message.
179 */
180 public void setMessageDetailMaximum(String maximumMessageDetail)
181 {
182 _facesBean.setProperty(_MAXIMUM_MESSAGE_DETAIL_KEY, maximumMessageDetail);
183 }
184
185 /**
186 * <p>Return custom detail error message that was set for creating {@link FacesMessage},
187 * for cases where input value exceeds the <code>maximum</code> value set.</p>
188 * @return Custom error message.
189 * @see #setMessageDetailMaximum(String)
190 */
191 public String getMessageDetailMaximum()
192 {
193 Object maxMsgDet = _facesBean.getProperty(_MAXIMUM_MESSAGE_DETAIL_KEY);
194 return ComponentUtils.resolveString(maxMsgDet);
195 }
196
197 /**
198 * <p>Custom error message to be used, for creating detail part of the
199 * {@link FacesMessage}, when input value is less the set
200 * <code>minimum</code> value.</p>
201 * Overrides detail message identified by message id {@link #MINIMUM_MESSAGE_ID}
202 * @param minimumMessageDetail Custom error message.
203 */
204 public void setMessageDetailMinimum(String minimumMessageDetail)
205 {
206 _facesBean.setProperty(_MINIMUM_MESSAGE_DETAIL_KEY, minimumMessageDetail);
207 }
208
209 /**
210 * <p>Return custom detail error message that was set for creating {@link FacesMessage},
211 * for cases where, input value is less than the <code>minimum</code> value set.</p>
212 * @return Custom error message.
213 * @see #setMessageDetailMinimum(String)
214 */
215 public String getMessageDetailMinimum()
216 {
217 Object minMsgDet = _facesBean.getProperty(_MINIMUM_MESSAGE_DETAIL_KEY);
218 return ComponentUtils.resolveString(minMsgDet);
219 }
220
221 /**
222 * <p>Custom error message to be used, for creating detail part of the
223 * {@link FacesMessage}, when input value is not with in the range,
224 * when <code>minimum</code> and <code>maximum</code> is set.</p>
225 * Overrides detail message identified by message id {@link #NOT_IN_RANGE_MESSAGE_ID}
226 * @param notInRangeMessageDetail Custom error message.
227 */
228 public void setMessageDetailNotInRange(String notInRangeMessageDetail)
229 {
230 _facesBean.setProperty(_NOT_IN_RANGE_MESSAGE_DETAIL_KEY, notInRangeMessageDetail);
231 }
232
233 /**
234 * <p>Return custom detail error message that was set for creating {@link FacesMessage},
235 * for cases where, input value exceeds the <code>maximum</code> value and is
236 * less than the <code>minimum</code> value set.</p>
237 * @return Custom error message.
238 * @see #setMessageDetailNotInRange(String)
239 */
240 public String getMessageDetailNotInRange()
241 {
242 Object notInRngMsg = _facesBean.getProperty(_NOT_IN_RANGE_MESSAGE_DETAIL_KEY);
243 return ComponentUtils.resolveString(notInRngMsg);
244 }
245
246 /**
247 * <p>Custom hint maximum message.</p>
248 * Overrides default hint message
249 * @param hintMaximum Custom hint message.
250 */
251 public void setHintMaximum(String hintMaximum)
252 {
253 _facesBean.setProperty(_HINT_MAXIMUM_KEY, hintMaximum);
254 }
255
256 /**
257 * <p>Return custom hint maximum message.</p>
258 * @return Custom hint message.
259 * @see #setHintMaximum(String)
260 */
261 public String getHintMaximum()
262 {
263 Object obj = _facesBean.getProperty(_HINT_MAXIMUM_KEY);
264 return ComponentUtils.resolveString(obj);
265 }
266
267 /**
268 * <p>Custom hint minimum message.</p>
269 * Overrides default hint message
270 * @param hintMinimum Custom hint message.
271 */
272 public void setHintMinimum(String hintMinimum)
273 {
274 _facesBean.setProperty(_HINT_MINIMUM_KEY, hintMinimum);
275 }
276
277 /**
278 * <p>Return custom hint minimum message.</p>
279 * @return Custom hint message.
280 * @see #setHintMinimum(String)
281 */
282 public String getHintMinimum()
283 {
284 Object obj = _facesBean.getProperty(_HINT_MINIMUM_KEY);
285 return ComponentUtils.resolveString(obj);
286 }
287
288 /**
289 * <p>Custom hint notInRange message.</p>
290 * Overrides default hint message
291 * @param hintNotInRange Custom hint message.
292 */
293 public void setHintNotInRange(String hintNotInRange)
294 {
295 _facesBean.setProperty(_HINT_NOT_IN_RANGE, hintNotInRange);
296 }
297
298 /**
299 * <p>Return custom hint notInRange message.</p>
300 * @return Custom hint message.
301 * @see #setHintNotInRange
302 */
303 public String getHintNotInRange()
304 {
305 Object obj = _facesBean.getProperty(_HINT_NOT_IN_RANGE);
306 return ComponentUtils.resolveString(obj);
307 }
308
309 @Override
310 public void validate(
311 FacesContext context,
312 UIComponent component,
313 Object value
314 ) throws ValidatorException
315 {
316 if ((context == null) || (component == null))
317 {
318 throw new NullPointerException();
319 }
320
321 if (value == null)
322 {
323 return;
324 }
325
326 try
327 {
328 long longValue = _convertValueToLong(value);
329 long min = getMinimum();
330 long max = getMaximum();
331
332 if(isMaximumSet() && isMinimumSet())
333 {
334 if(longValue<min || longValue>max)
335 {
336 throw new ValidatorException(
337 _getNotInRangeMessage(context, component, value, min, max));
338 }
339 }
340
341 if(isMaximumSet())
342 {
343 if (longValue > max)
344 {
345 throw new ValidatorException(
346 _getMaximumMessage(context, component, value, IntegerUtils.getString(max)));
347 }
348 }
349
350 if(isMinimumSet())
351 {
352 if (longValue < min)
353 {
354 throw new ValidatorException(
355 _getMinimumMessage(context, component, value, IntegerUtils.getString(min)));
356 }
357 }
358 }
359 catch (NumberFormatException nfe)
360 {
361 FacesMessage msg = _getNotCorrectType(context);
362 throw new ValidatorException(msg);
363 }
364 }
365
366
367 @Override
368 public Object saveState(FacesContext context)
369 {
370 return _facesBean.saveState(context);
371 }
372
373
374 @Override
375 public void restoreState(FacesContext context, Object state)
376 {
377 _facesBean.restoreState(context, state);
378 }
379
380 /**
381 * <p>Set the {@link ValueExpression} used to calculate the value for the
382 * specified attribute if any.</p>
383 *
384 * @param name Name of the attribute for which to set a {@link ValueExpression}
385 * @param expression The {@link ValueExpression} to set, or <code>null</code>
386 * to remove any currently set {@link ValueExpression}
387 *
388 * @exception NullPointerException if <code>name</code>
389 * is <code>null</code>
390 * @exception IllegalArgumentException if <code>name</code> is not a valid
391 * attribute of this converter
392 */
393 public void setValueExpression(String name, ValueExpression expression)
394 {
395 ValidatorUtils.setValueExpression(_facesBean, name, expression) ;
396 }
397
398
399 /**
400 * <p>Return the {@link ValueExpression} used to calculate the value for the
401 * specified attribute name, if any.</p>
402 *
403 * @param name Name of the attribute or property for which to retrieve a
404 * {@link ValueExpression}
405 *
406 * @exception NullPointerException if <code>name</code>
407 * is <code>null</code>
408 * @exception IllegalArgumentException if <code>name</code> is not a valid
409 * attribute of this converter
410 */
411 public ValueExpression getValueExpression(String name)
412 {
413 return ValidatorUtils.getValueExpression(_facesBean, name);
414 }
415
416
417 /**
418 * <p>Set the {@link ValueBinding} used to calculate the value for the
419 * specified attribute if any.</p>
420 *
421 * @param name Name of the attribute for which to set a {@link ValueBinding}
422 * @param binding The {@link ValueBinding} to set, or <code>null</code>
423 * to remove any currently set {@link ValueBinding}
424 *
425 * @exception NullPointerException if <code>name</code>
426 * is <code>null</code>
427 * @exception IllegalArgumentException if <code>name</code> is not a valid
428 * attribute of this validator
429 * @deprecated
430 */
431 public void setValueBinding(String name, ValueBinding binding)
432 {
433 ValidatorUtils.setValueBinding(_facesBean, name, binding) ;
434 }
435
436 /**
437 * <p>Return the {@link ValueBinding} used to calculate the value for the
438 * specified attribute name, if any.</p>
439 *
440 * @param name Name of the attribute or property for which to retrieve a
441 * {@link ValueBinding}
442 *
443 * @exception NullPointerException if <code>name</code>
444 * is <code>null</code>
445 * @exception IllegalArgumentException if <code>name</code> is not a valid
446 * attribute of this validator
447 * @deprecated
448 */
449 public ValueBinding getValueBinding(String name)
450 {
451 return ValidatorUtils.getValueBinding(_facesBean, name);
452 }
453
454 @Override
455 public boolean isTransient()
456 {
457 return (_transientValue);
458 }
459
460
461 @Override
462 public void setTransient(boolean transientValue)
463 {
464 _transientValue = transientValue;
465 }
466
467 protected boolean isMaximumSet()
468 {
469 return _facesBean.getProperty(_MAXIMUM_KEY) != null;
470 }
471
472 protected boolean isMinimumSet()
473 {
474 return _facesBean.getProperty(_MINIMUM_KEY) != null;
475 }
476
477 private FacesMessage _getNotCorrectType(
478 FacesContext context)
479 {
480 return MessageFactory.getMessage(context, CONVERT_MESSAGE_ID);
481 }
482
483 /**
484 * Try to call longValue() from java.lang.Number. Since not all
485 * "number" implement java.lang.Number, we try to call string
486 * and parse the String representation of the "number". If that fails
487 * we aren't working with a number so we throw a NumberFormatException
488 *
489 * @param value the number value
490 * @return parsed number value
491 * @throws NumberFormatException if the value is not a number
492 */
493 private long _convertValueToLong(Object value) throws NumberFormatException
494 {
495 if(value instanceof Number)
496 {
497 return ((Number)value).longValue();
498 }
499 else
500 {
501 return Long.parseLong(value.toString());
502 }
503 }
504
505 private FacesMessage _getNotInRangeMessage(
506 FacesContext context,
507 UIComponent component,
508 Object value,
509 Object min,
510 Object max)
511 {
512 Object msg = _getRawNotInRangeMessageDetail();
513 Object label = ValidatorUtils.getComponentLabel(component);
514
515 Object[] params = {label, value, min, max};
516
517 return MessageFactory.getMessage(context, NOT_IN_RANGE_MESSAGE_ID,
518 msg, params, component);
519 }
520
521
522
523 private Object _getRawNotInRangeMessageDetail()
524 {
525 return _facesBean.getRawProperty(_NOT_IN_RANGE_MESSAGE_DETAIL_KEY);
526 }
527
528
529 private FacesMessage _getMaximumMessage(
530 FacesContext context,
531 UIComponent component,
532 Object value,
533 Object max)
534 {
535
536 Object msg = _getRawMaximumMessageDetail();
537 Object label = ValidatorUtils.getComponentLabel(component);
538
539 Object[] params = {label, value, max};
540
541 return MessageFactory.getMessage(context,
542 MAXIMUM_MESSAGE_ID,
543 msg,
544 params,
545 component);
546 }
547
548 private Object _getRawMaximumMessageDetail()
549 {
550 return _facesBean.getRawProperty(_MAXIMUM_MESSAGE_DETAIL_KEY);
551 }
552
553 private FacesMessage _getMinimumMessage(
554 FacesContext context,
555 UIComponent component,
556 Object value,
557 Object min)
558 {
559 Object msg = _getRawMinimumMessageDetail();
560 Object label = ValidatorUtils.getComponentLabel(component);
561
562 Object[] params = {label, value, min};
563
564 return MessageFactory.getMessage(context, MINIMUM_MESSAGE_ID,
565 msg, params, component);
566 }
567
568 private Object _getRawMinimumMessageDetail()
569 {
570 return _facesBean.getRawProperty(_MINIMUM_MESSAGE_DETAIL_KEY);
571 }
572
573 private static final FacesBean.Type _TYPE = new FacesBean.Type();
574
575 private static final PropertyKey _MINIMUM_KEY =
576 _TYPE.registerKey("minimum", Long.class,
577
578 Long.valueOf(Long.MIN_VALUE));
579
580 private static final PropertyKey _MAXIMUM_KEY =
581 _TYPE.registerKey("maximum", Long.class,
582
583 Long.valueOf(Long.MAX_VALUE));
584
585 private static final PropertyKey _MAXIMUM_MESSAGE_DETAIL_KEY =
586 _TYPE.registerKey("messageDetailMaximum", String.class);
587
588 private static final PropertyKey _MINIMUM_MESSAGE_DETAIL_KEY =
589 _TYPE.registerKey("messageDetailMinimum", String.class);
590
591 private static final PropertyKey _NOT_IN_RANGE_MESSAGE_DETAIL_KEY =
592 _TYPE.registerKey("messageDetailNotInRange", String.class);
593
594 private static final PropertyKey _HINT_MAXIMUM_KEY =
595 _TYPE.registerKey("hintMaximum", String.class);
596
597 private static final PropertyKey _HINT_MINIMUM_KEY =
598 _TYPE.registerKey("hintMinimum", String.class);
599
600 private static final PropertyKey _HINT_NOT_IN_RANGE =
601 _TYPE.registerKey("hintNotInRange", String.class);
602
603 private FacesBean _facesBean = ValidatorUtils.getFacesBean(_TYPE);
604
605 private boolean _transientValue = false;
606 }