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 import javax.faces.validator.Validator;
29 import javax.faces.validator.ValidatorException;
30
31 import org.apache.myfaces.trinidad.bean.FacesBean;
32 import org.apache.myfaces.trinidad.bean.PropertyKey;
33 import org.apache.myfaces.trinidad.util.ComponentUtils;
34 import org.apache.myfaces.trinidad.util.MessageFactory;
35
36 /**
37 * <p>Implementation for length of <code>java.lang.String</code> values.</p>
38 *
39 */
40 public class LengthValidator extends javax.faces.validator.LengthValidator
41 {
42
43 public static final String VALIDATOR_ID = "org.apache.myfaces.trinidad.Length";
44
45 /**
46 * <p>The message identifier of the {@link javax.faces.application.FacesMessage}
47 * to be created if the maximum length check fails. The message format
48 * string for this message may optionally include <code>{0}</code>,
49 * <code>{1}</code> and <code>{3}</code> placeholders,
50 * which will be replaced by user input, component label and configured
51 * maximum length.</p>
52 */
53 public static final String MAXIMUM_MESSAGE_ID =
54 "org.apache.myfaces.trinidad.validator.LengthValidator.MAXIMUM";
55
56 /**
57 * <p>The message identifier of the {@link javax.faces.application.FacesMessage}
58 * to be created if the minimum length check fails. The message format
59 * string for this message may optionally include <code>{0}</code>,
60 * <code>{1}</code> and <code>{2}</code> placeholders, which will be replaced
61 * by user input, component label and configured minimum length.</p>
62 */
63 public static final String MINIMUM_MESSAGE_ID =
64 "org.apache.myfaces.trinidad.validator.LengthValidator.MINIMUM";
65
66
67 /**
68 * <p>The message identifier of the {@link javax.faces.application.FacesMessage}
69 * to be created if the maximum or minimum length check fails, and both
70 * the maximum and minimum lengths for this validator have been set.
71 * The message format string for this message may optionally include
72 * <code>{0}</code>, <code>{1}</code>, <code>{2}</code> and <code>{3}</code>
73 * placeholders, which will be replaced by user input, component label,
74 * configured minimum length and configured maximum length.</p>
75 */
76 public static final String NOT_IN_RANGE_MESSAGE_ID =
77 "org.apache.myfaces.trinidad.validator.LengthValidator.NOT_IN_RANGE";
78
79 /**
80 * <p>The message identifier of the {@link javax.faces.application.FacesMessage}
81 * to be created if the maximum and minimum lengths are the same,
82 * and the length check fails, and both
83 * the maximum and minimum values for this validator have been set.
84 * The message format string for this message may optionally include
85 * <code>{0}</code>, <code>{1}</code>, <code>{2}</code>
86 * placeholders, which will be replaced by user input, component label,
87 * configured minimum/maximum length.</p>
88 */
89 public static final String EXACT_MESSAGE_ID =
90 "org.apache.myfaces.trinidad.validator.LengthValidator.EXACT";
91
92
93 /**
94 * Construct a {@link Validator} with no preconfigured limits.
95 */
96 public LengthValidator()
97 {
98 super();
99 }
100
101 /**
102 * Construct a {@link Validator} with the specified preconfigured
103 * limit.
104 *
105 * @param maximum Maximum length to allow
106 */
107 public LengthValidator(int maximum)
108 {
109 super(maximum);
110 }
111
112 /**
113 * Construct a {@link Validator} with the specified preconfigured
114 * limits.
115 *
116 * @param maximum Maximum length to allow
117 * @param minimum Minimum length to allow
118 *
119 */
120 public LengthValidator(int maximum, int minimum)
121 {
122 super(maximum, minimum);
123 }
124
125 /**
126 * Return the maximum length to be enforced by this {@link
127 * Validator} or null if it has not been
128 * set.
129 */
130 @Override
131 public int getMaximum()
132 {
133 Object maxInt = _facesBean.getProperty(_MAXIMUM_KEY);
134 return ComponentUtils.resolveInteger(maxInt);
135 }
136
137 /**
138 * Set the maximum length to be enforced by this {@link Validator}.
139 *
140 * @param maximum The new maximum length
141 *
142 */
143 @Override
144 public void setMaximum(int maximum)
145 {
146 _facesBean.setProperty(_MAXIMUM_KEY, Integer.valueOf(maximum));
147 }
148
149
150 /**
151 * Return the minimum length to be enforced by this {@link
152 * Validator}, or null if it has not been
153 * set.
154 */
155 @Override
156 public int getMinimum()
157 {
158 Object minInt = _facesBean.getProperty(_MINIMUM_KEY);
159 return ComponentUtils.resolveInteger(minInt);
160 }
161
162 /**
163 * Set the minimum length to be enforced by this {@link Validator}.
164 *
165 * @param minimum The new minimum length
166 *
167 */
168 @Override
169 public void setMinimum(int minimum)
170 {
171 _facesBean.setProperty(_MINIMUM_KEY, Integer.valueOf(minimum));
172 }
173
174 /**
175 * <p>Custom error message to be used, for creating detail part of the
176 * {@link FacesMessage}, when input length exceeds the maximum length 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 length exceeds the <code>maximum</code> length 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 length is less the set
200 * <code>minimum</code> length.</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 length is less than the <code>minimum</code> length 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 length 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 length exceeds the <code>maximum</code> length and is
236 * less than the <code>minimum</code> length 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 /**
248 * <p>Custom error message to be used, for creating detail part of the
249 * {@link FacesMessage},
250 * for cases where the maximum and minimum lengths are the same, and
251 * the input length does not match.
252 * Overrides detail message identified by message id {@link #EXACT_MESSAGE_ID}
253 * @param exactMessageDetail Custom error message.
254 */
255 public void setMessageDetailExact(String exactMessageDetail)
256 {
257 _facesBean.setProperty(_EXACT_MESSAGE_DETAIL_KEY, exactMessageDetail);
258 }
259
260 /**
261 * <p>Return custom detail error message that was set for creating {@link FacesMessage},
262 * for cases where the maximum and minimum lengths are the same, and
263 * the input length does not match.</p>
264 * @return Custom error message.
265 * @see #setMessageDetailExact(String)
266 */
267 public String getMessageDetailExact()
268 {
269 Object msg = _facesBean.getProperty(_EXACT_MESSAGE_DETAIL_KEY);
270 return ComponentUtils.resolveString(msg);
271 }
272
273
274 /**
275 * <p>Custom hint maximum message.</p>
276 * Overrides default hint message
277 * @param hintMaximum Custom hint message.
278 */
279 public void setHintMaximum(String hintMaximum)
280 {
281 _facesBean.setProperty(_HINT_MAXIMUM_KEY, hintMaximum);
282 }
283
284 /**
285 * <p>Return custom hint maximum message.</p>
286 * @return Custom hint message.
287 * @see #setHintMaximum(String)
288 */
289 public String getHintMaximum()
290 {
291 Object obj = _facesBean.getProperty(_HINT_MAXIMUM_KEY);
292 return ComponentUtils.resolveString(obj);
293 }
294
295 /**
296 * <p>Custom hint minimum message.</p>
297 * Overrides default hint message
298 * @param hintMinimum Custom hint message.
299 */
300 public void setHintMinimum(String hintMinimum)
301 {
302 _facesBean.setProperty(_HINT_MINIMUM_KEY, hintMinimum);
303 }
304
305 /**
306 * <p>Return custom hint minimum message.</p>
307 * @return Custom hint message.
308 * @see #setHintMinimum(String)
309 */
310 public String getHintMinimum()
311 {
312 Object obj = _facesBean.getProperty(_HINT_MINIMUM_KEY);
313 return ComponentUtils.resolveString(obj);
314 }
315
316 /**
317 * <p>Custom hint notInRange message.</p>
318 * Overrides default hint message
319 * @param hintNotInRange Custom hint message.
320 */
321 public void setHintNotInRange(String hintNotInRange)
322 {
323 _facesBean.setProperty(_HINT_NOT_IN_RANGE, hintNotInRange);
324 }
325
326 /**
327 * <p>Return custom hint notInRange message.</p>
328 * @return Custom hint message.
329 * @see #setHintNotInRange
330 */
331 public String getHintNotInRange()
332 {
333 Object obj = _facesBean.getProperty(_HINT_NOT_IN_RANGE);
334 return ComponentUtils.resolveString(obj);
335 }
336
337
338 /**
339 * <p>Custom hint exact message.</p>
340 * Overrides default hint message
341 * @param hintExact Custom hint message.
342 */
343 public void setHintExact(String hintExact)
344 {
345 _facesBean.setProperty(_HINT_EXACT, hintExact);
346 }
347
348 /**
349 * <p>Return custom hint exact message.</p>
350 * @return Custom hint message.
351 * @see #setHintExact
352 */
353 public String getHintExact()
354 {
355 Object obj = _facesBean.getProperty(_HINT_EXACT);
356 return ComponentUtils.resolveString(obj);
357 }
358
359 @Override
360 public void validate(
361 FacesContext context,
362 UIComponent component,
363 Object value
364 ) throws ValidatorException
365 {
366 if ((context == null) || (component == null))
367 {
368 throw new NullPointerException();
369 }
370
371 if(value != null)
372 {
373 int max = getMaximum();
374 int min = getMinimum();
375 int length = value instanceof String ?
376 ((String)value).length() : value.toString().length();
377
378
379 if(isMaximumSet() && isMinimumSet())
380 {
381 if(length<min || length>max)
382 {
383 throw new ValidatorException(
384 _getNotInRangeMessage(context, component, value, min, max));
385 }
386 }
387
388 if(isMinimumSet())
389 {
390 if (length < min)
391 {
392 throw new ValidatorException(
393 _getMinimumMessage(context, component, value, min));
394 }
395 }
396
397 if(isMaximumSet())
398 {
399 if (length > max)
400 {
401 throw new ValidatorException(
402 _getMaximumMessage(context, component, value, max));
403 }
404 }
405 }
406 }
407
408
409 @Override
410 public Object saveState(FacesContext context)
411 {
412 return _facesBean.saveState(context);
413 }
414
415
416 @Override
417 public void restoreState(FacesContext context, Object state)
418 {
419 _facesBean.restoreState(context, state);
420 }
421
422 /**
423 * <p>Set the {@link ValueExpression} used to calculate the value for the
424 * specified attribute if any.</p>
425 *
426 * @param name Name of the attribute for which to set a {@link ValueExpression}
427 * @param expression The {@link ValueExpression} to set, or <code>null</code>
428 * to remove any currently set {@link ValueExpression}
429 *
430 * @exception NullPointerException if <code>name</code>
431 * is <code>null</code>
432 * @exception IllegalArgumentException if <code>name</code> is not a valid
433 * attribute of this converter
434 */
435 public void setValueExpression(String name, ValueExpression expression)
436 {
437 ValidatorUtils.setValueExpression(_facesBean, name, expression) ;
438 }
439
440
441 /**
442 * <p>Return the {@link ValueExpression} used to calculate the value for the
443 * specified attribute name, if any.</p>
444 *
445 * @param name Name of the attribute or property for which to retrieve a
446 * {@link ValueExpression}
447 *
448 * @exception NullPointerException if <code>name</code>
449 * is <code>null</code>
450 * @exception IllegalArgumentException if <code>name</code> is not a valid
451 * attribute of this converter
452 */
453 public ValueExpression getValueExpression(String name)
454 {
455 return ValidatorUtils.getValueExpression(_facesBean, name);
456 }
457
458
459 /**
460 * <p>Set the {@link ValueBinding} used to calculate the value for the
461 * specified attribute if any.</p>
462 *
463 * @param name Name of the attribute for which to set a {@link ValueBinding}
464 * @param binding The {@link ValueBinding} to set, or <code>null</code>
465 * to remove any currently set {@link ValueBinding}
466 *
467 * @exception NullPointerException if <code>name</code>
468 * is <code>null</code>
469 * @exception IllegalArgumentException if <code>name</code> is not a valid
470 * attribute of this validator
471 * @deprecated
472 */
473 public void setValueBinding(String name, ValueBinding binding)
474 {
475 ValidatorUtils.setValueBinding(_facesBean, name, binding) ;
476 }
477
478 /**
479 * <p>Return the {@link ValueBinding} used to calculate the value for the
480 * specified attribute name, if any.</p>
481 *
482 * @param name Name of the attribute or property for which to retrieve a
483 * {@link ValueBinding}
484 *
485 * @exception NullPointerException if <code>name</code>
486 * is <code>null</code>
487 * @exception IllegalArgumentException if <code>name</code> is not a valid
488 * attribute of this validator
489 * @deprecated
490 */
491 public ValueBinding getValueBinding(String name)
492 {
493 return ValidatorUtils.getValueBinding(_facesBean, name);
494 }
495
496 @Override
497 public boolean isTransient()
498 {
499 return (_transientValue);
500 }
501
502
503 @Override
504 public void setTransient(boolean transientValue)
505 {
506 _transientValue = transientValue;
507 }
508
509 protected boolean isMaximumSet()
510 {
511 return _facesBean.getProperty(_MAXIMUM_KEY) != null;
512 }
513
514 protected boolean isMinimumSet()
515 {
516 return _facesBean.getProperty(_MINIMUM_KEY) != null;
517 }
518
519 private FacesMessage _getNotInRangeMessage(
520 FacesContext context,
521 UIComponent component,
522 Object value,
523 Object min,
524 Object max)
525 {
526 if (min.equals(max))
527 return _getExactMessage(context, component, value, min);
528
529 Object msg = _getRawNotInRangeMessageDetail();
530 Object label = ValidatorUtils.getComponentLabel(component);
531
532 Object[] params = {label, value, min, max};
533
534 return MessageFactory.getMessage(context, NOT_IN_RANGE_MESSAGE_ID,
535 msg, params, component);
536 }
537
538
539 private Object _getRawNotInRangeMessageDetail()
540 {
541 return _facesBean.getRawProperty(_NOT_IN_RANGE_MESSAGE_DETAIL_KEY);
542 }
543
544
545 private FacesMessage _getExactMessage(
546 FacesContext context,
547 UIComponent component,
548 Object value,
549 Object minMax)
550 {
551 Object msg = _getRawExactMessageDetail();
552 Object label = ValidatorUtils.getComponentLabel(component);
553
554 Object[] params = {label, value, minMax};
555
556 return MessageFactory.getMessage(context, EXACT_MESSAGE_ID,
557 msg, params, component);
558 }
559
560
561 private Object _getRawExactMessageDetail()
562 {
563 return _facesBean.getRawProperty(_EXACT_MESSAGE_DETAIL_KEY);
564 }
565
566
567 private FacesMessage _getMaximumMessage(
568 FacesContext context,
569 UIComponent component,
570 Object value,
571 Object max)
572 {
573
574 Object msg = _getRawMaximumMessageDetail();
575 Object label = ValidatorUtils.getComponentLabel(component);
576
577 Object[] params = {label, value, max};
578
579 return MessageFactory.getMessage(context,
580 MAXIMUM_MESSAGE_ID,
581 msg,
582 params,
583 component);
584 }
585
586 private Object _getRawMaximumMessageDetail()
587 {
588 return _facesBean.getRawProperty(_MAXIMUM_MESSAGE_DETAIL_KEY);
589 }
590
591 private FacesMessage _getMinimumMessage(
592 FacesContext context,
593 UIComponent component,
594 Object value,
595 Object min)
596 {
597 Object msg = _getRawMinimumMessageDetail();
598 Object label = ValidatorUtils.getComponentLabel(component);
599
600 Object[] params = {label, value, min};
601
602 return MessageFactory.getMessage(context, MINIMUM_MESSAGE_ID,
603 msg, params, component);
604 }
605
606 private Object _getRawMinimumMessageDetail()
607 {
608 return _facesBean.getRawProperty(_MINIMUM_MESSAGE_DETAIL_KEY);
609 }
610
611 private static final FacesBean.Type _TYPE = new FacesBean.Type();
612
613
614 private static final PropertyKey _MINIMUM_KEY =
615 _TYPE.registerKey("minimum",
616 Integer.class,
617
618 Integer.valueOf(0));
619
620
621 private static final PropertyKey _MAXIMUM_KEY =
622 _TYPE.registerKey("maximum", Integer.class,
623
624 Integer.valueOf(0));
625
626 private static final PropertyKey _MAXIMUM_MESSAGE_DETAIL_KEY =
627 _TYPE.registerKey("messageDetailMaximum", String.class);
628
629 private static final PropertyKey _MINIMUM_MESSAGE_DETAIL_KEY =
630 _TYPE.registerKey("messageDetailMinimum", String.class);
631
632 private static final PropertyKey _NOT_IN_RANGE_MESSAGE_DETAIL_KEY =
633 _TYPE.registerKey("messageDetailNotInRange", String.class);
634
635 private static final PropertyKey _EXACT_MESSAGE_DETAIL_KEY =
636 _TYPE.registerKey("messageDetailExact", String.class);
637
638 private static final PropertyKey _HINT_MAXIMUM_KEY =
639 _TYPE.registerKey("hintMaximum", String.class);
640
641 private static final PropertyKey _HINT_MINIMUM_KEY =
642 _TYPE.registerKey("hintMinimum", String.class);
643
644 private static final PropertyKey _HINT_NOT_IN_RANGE =
645 _TYPE.registerKey("hintNotInRange", String.class);
646
647 private static final PropertyKey _HINT_EXACT =
648 _TYPE.registerKey("hintExact", String.class);
649
650 private FacesBean _facesBean = ValidatorUtils.getFacesBean(_TYPE);
651
652 private boolean _transientValue = false;
653 }