View Javadoc

1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    * 
10   *  http://www.apache.org/licenses/LICENSE-2.0
11   * 
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   */
19  package org.apache.myfaces.trinidad.validator;
20  
21  import javax.faces.application.FacesMessage;
22  import javax.faces.component.UIComponent;
23  import javax.faces.context.FacesContext;
24  import javax.faces.el.ValueBinding;
25  
26  import javax.faces.validator.Validator;
27  import javax.faces.validator.ValidatorException;
28  
29  import org.apache.myfaces.trinidad.bean.FacesBean;
30  import org.apache.myfaces.trinidad.bean.PropertyKey;
31  import org.apache.myfaces.trinidad.util.ComponentUtils;
32  import org.apache.myfaces.trinidad.util.IntegerUtils;
33  import org.apache.myfaces.trinidad.util.MessageFactory;
34  
35  /**
36   * <p>Implementation for <code>java.lang.Long</code> values.</p>
37   *
38   */
39  public class LongRangeValidator extends javax.faces.validator.LongRangeValidator
40  {
41    
42    public static final String VALIDATOR_ID = "org.apache.myfaces.trinidad.LongRange";
43  
44    /**
45     * <p>The message identifier of the {@link javax.faces.application.FacesMessage}
46     * to be created if the maximum value check fails.  The message format
47     * string for this message may optionally include <code>{0}</code>,
48     * <code>{1}</code> and <code>{3}</code> placeholders,
49     * which will be replaced by user input, component label and configured
50     * maximum value.</p>
51     */
52    public static final String MAXIMUM_MESSAGE_ID =
53        "org.apache.myfaces.trinidad.validator.LongRangeValidator.MAXIMUM";
54  
55    /**
56     * <p>The message identifier of the {@link javax.faces.application.FacesMessage}
57     * to be created if the minimum value check fails.  The message format
58     * string for this message may optionally include <code>{0}</code>,
59     * <code>{1}</code> and <code>{2}</code> placeholders, which will be replaced
60     * by user input, component label and configured minimum value.</p>
61     */
62    public static final String MINIMUM_MESSAGE_ID =
63        "org.apache.myfaces.trinidad.validator.LongRangeValidator.MINIMUM";
64  
65  
66    /**
67     * <p>The message identifier of the {@link javax.faces.application.FacesMessage}
68     * to be created if the maximum or minimum value check fails, and both
69     * the maximum and minimum values for this validator have been set.
70     * The message format string for this message may optionally include
71     * <code>{0}</code>, <code>{1}</code>, <code>{2}</code> and <code>{3}</code>
72     * placeholders, which will be replaced by user input, component label,
73     * configured minimum value and configured maximum value.</p>
74     */
75    public static final String NOT_IN_RANGE_MESSAGE_ID =
76        "org.apache.myfaces.trinidad.validator.LongRangeValidator.NOT_IN_RANGE";
77  
78    
79    /**
80     * Construct a {@link Validator} with no preconfigured limits.
81     */
82    public LongRangeValidator()
83    {
84      super();
85    }
86  
87    /**
88     * Construct a {@link Validator} with the specified preconfigured
89     * limit.
90     *
91     * @param maximum Maximum value to allow
92     */
93    public LongRangeValidator(long maximum)
94    {
95      super(maximum);
96    }
97  
98    /**
99     * Construct a {@link Validator} with the specified preconfigured
100    * limits.
101    *
102    * @param maximum Maximum value to allow
103    * @param minimum Minimum value to allow
104    *
105    */
106   public LongRangeValidator(long maximum, long minimum)
107   {
108     super(maximum, minimum);
109   }
110   
111   /**
112    * Return the maximum value to be enforced by this {@link
113    * Validator} or null if it has not been
114    * set.
115    */
116   @Override
117   public long getMaximum()
118   {
119     Object maxLong = _facesBean.getProperty(_MAXIMUM_KEY);
120     if(maxLong == null)
121       maxLong = Long.MAX_VALUE;
122     return ComponentUtils.resolveLong(maxLong);
123   }
124 
125   /**
126    * Set the maximum value to be enforced by this {@link Validator}.
127    *
128    * @param maximum The new maximum value
129    *
130    */
131   @Override
132   public void setMaximum(long maximum)
133   {
134     super.setMaximum(maximum);
135     _facesBean.setProperty(_MAXIMUM_KEY, Long.valueOf(maximum));
136   }
137 
138 
139   /**
140    * Return the minimum value to be enforced by this {@link
141    * Validator}, or null if it has not been
142    * set.
143    */
144   @Override
145   public long getMinimum()
146   {
147     Object minLong = _facesBean.getProperty(_MINIMUM_KEY);
148     if(minLong == null)
149       minLong = Long.MIN_VALUE;
150     return ComponentUtils.resolveLong(minLong);
151   }
152 
153   /**
154    * Set the minimum value to be enforced by this {@link Validator}.
155    *
156    * @param minimum The new minimum value
157    *
158    */
159   @Override
160   public void setMinimum(long minimum)
161   {
162     super.setMinimum(minimum);
163     _facesBean.setProperty(_MINIMUM_KEY, Long.valueOf(minimum));
164   }
165 
166   /**
167    * <p>Custom error message to be used, for creating detail part of the
168    * {@link FacesMessage}, when input value exceeds the maximum value set.</p>
169    * Overrides detail message identified by message id {@link #MAXIMUM_MESSAGE_ID}
170    * @param maximumMessageDetail Custom error message.
171    */
172   public void setMessageDetailMaximum(String maximumMessageDetail)
173   {
174     _facesBean.setProperty(_MAXIMUM_MESSAGE_DETAIL_KEY, maximumMessageDetail);
175   }
176 
177   /**
178    *  <p>Return custom detail error message that was set for creating {@link FacesMessage},
179    *  for cases where input value exceeds the <code>maximum</code> value set.</p>
180    * @return Custom error message.
181    * @see #setMessageDetailMaximum(String)
182    */
183   public String getMessageDetailMaximum()
184   {
185     Object maxMsgDet = _facesBean.getProperty(_MAXIMUM_MESSAGE_DETAIL_KEY);
186     return ComponentUtils.resolveString(maxMsgDet);
187   }
188 
189   /**
190    * <p>Custom error message to be used, for creating detail part of the
191    * {@link FacesMessage}, when input value is less the set
192    * <code>minimum</code> value.</p>
193    * Overrides detail message identified by message id {@link #MINIMUM_MESSAGE_ID}
194    * @param minimumMessageDetail Custom error message.
195    */
196   public void setMessageDetailMinimum(String minimumMessageDetail)
197   {
198     _facesBean.setProperty(_MINIMUM_MESSAGE_DETAIL_KEY, minimumMessageDetail);
199   }
200 
201   /**
202    * <p>Return custom detail error message that was set for creating {@link FacesMessage},
203    * for cases where, input value is less than the <code>minimum</code> value set.</p>
204    * @return Custom error message.
205    * @see #setMessageDetailMinimum(String)
206    */
207   public String getMessageDetailMinimum()
208   {
209     Object minMsgDet = _facesBean.getProperty(_MINIMUM_MESSAGE_DETAIL_KEY);
210     return ComponentUtils.resolveString(minMsgDet);
211   }
212 
213   /**
214    * <p>Custom error message to be used, for creating detail part of the
215    * {@link FacesMessage}, when input value is not with in the range,
216    * when <code>minimum</code> and <code>maximum</code> is set.</p>
217    * Overrides detail message identified by message id {@link #NOT_IN_RANGE_MESSAGE_ID}
218    * @param notInRangeMessageDetail Custom error message.
219    */
220   public void setMessageDetailNotInRange(String notInRangeMessageDetail)
221   {
222     _facesBean.setProperty(_NOT_IN_RANGE_MESSAGE_DETAIL_KEY, notInRangeMessageDetail);
223   }
224 
225   /**
226    * <p>Return custom detail error message that was set for creating {@link FacesMessage},
227    * for cases where, input value exceeds the <code>maximum</code> value and is
228    * less than the <code>minimum</code> value set.</p>
229    * @return Custom error message.
230    * @see #setMessageDetailNotInRange(String)
231    */
232   public String getMessageDetailNotInRange()
233   {
234     Object notInRngMsg = _facesBean.getProperty(_NOT_IN_RANGE_MESSAGE_DETAIL_KEY);
235     return ComponentUtils.resolveString(notInRngMsg);
236   }
237 
238   /**
239    * <p>Custom hint maximum message.</p>
240    * Overrides default hint message
241    * @param hintMaximum Custom hint message.
242    */
243   public void setHintMaximum(String hintMaximum)
244   {
245     _facesBean.setProperty(_HINT_MAXIMUM_KEY, hintMaximum);
246   }
247 
248   /**
249    * <p>Return custom hint maximum message.</p>
250    * @return Custom hint message.
251    * @see  #setHintMaximum(String)
252    */
253   public String getHintMaximum()
254   {
255     Object obj = _facesBean.getProperty(_HINT_MAXIMUM_KEY);
256     return ComponentUtils.resolveString(obj);
257   }
258 
259   /**
260    * <p>Custom hint minimum message.</p>
261    * Overrides default hint message
262    * @param hintMinimum Custom hint message.
263    */
264   public void setHintMinimum(String hintMinimum)
265   {
266     _facesBean.setProperty(_HINT_MINIMUM_KEY, hintMinimum);
267   }
268 
269   /**
270    * <p>Return custom hint minimum message.</p>
271    * @return Custom hint message.
272    * @see  #setHintMinimum(String)
273    */
274   public String getHintMinimum()
275   {
276     Object obj = _facesBean.getProperty(_HINT_MINIMUM_KEY);
277     return ComponentUtils.resolveString(obj);
278   }
279 
280   /**
281    * <p>Custom hint notInRange message.</p>
282    * Overrides default hint message
283    * @param hintNotInRange Custom hint message.
284    */
285   public void setHintNotInRange(String hintNotInRange)
286   {
287     _facesBean.setProperty(_HINT_NOT_IN_RANGE, hintNotInRange);
288   }
289 
290   /**
291    * <p>Return custom hint notInRange message.</p>
292    * @return Custom hint message.
293    * @see  #setHintNotInRange
294    */
295   public String getHintNotInRange()
296   {
297     Object obj = _facesBean.getProperty(_HINT_NOT_IN_RANGE);
298     return ComponentUtils.resolveString(obj);
299   }
300   
301   @Override
302   public void validate(
303     FacesContext context,
304     UIComponent component,
305     Object value
306     ) throws ValidatorException
307   {
308     try
309     {
310       super.validate(context, component, value);
311     }
312     catch (ValidatorException ve)
313     {
314          
315       if (value != null && value instanceof Number)
316       {
317         long longValue = ((Number)value).longValue(); 
318         
319         long min = getMinimum();
320         long max = getMaximum();
321         
322         if (longValue > max)
323         {
324           if (min != Long.MIN_VALUE)//the default...
325           {
326              throw new ValidatorException
327                         (_getNotInRangeMessage(context, component, value, IntegerUtils.getString(min), IntegerUtils.getString(max)));
328           }
329           else
330           {
331              throw new ValidatorException
332                         (_getMaximumMessage(context, component, value, IntegerUtils.getString(max)));
333           }
334         }
335 
336         if (longValue < min)
337         {
338           if (max != Long.MAX_VALUE)//the default...
339           {
340             throw new ValidatorException
341                         (_getNotInRangeMessage(context, component, value, IntegerUtils.getString(min), IntegerUtils.getString(max)));
342           }
343           else
344           {
345             FacesMessage msg = _getMinimumMessage(context, component, value, IntegerUtils.getString(min));
346             throw new ValidatorException(msg);
347           }
348         }
349       }
350       else
351       {
352         throw ve;
353       }
354     }     
355   }
356 
357   //  StateHolder Methods
358   @Override
359   public Object saveState(FacesContext context)
360   {
361     return _facesBean.saveState(context);
362   }
363 
364 
365   @Override
366   public void restoreState(FacesContext context, Object state)
367   {
368     _facesBean.restoreState(context, state);
369   }
370 
371   /**
372    * <p>Set the {@link ValueBinding} used to calculate the value for the
373    * specified attribute if any.</p>
374    *
375    * @param name Name of the attribute for which to set a {@link ValueBinding}
376    * @param binding The {@link ValueBinding} to set, or <code>null</code>
377    *  to remove any currently set {@link ValueBinding}
378    *
379    * @exception NullPointerException if <code>name</code>
380    *  is <code>null</code>
381    * @exception IllegalArgumentException if <code>name</code> is not a valid
382    *            attribute of this validator
383    */
384   public void setValueBinding(String name, ValueBinding binding)
385   {
386     ValidatorUtils.setValueBinding(_facesBean, name, binding) ;
387   }
388 
389   /**
390    * <p>Return the {@link ValueBinding} used to calculate the value for the
391    * specified attribute name, if any.</p>
392    *
393    * @param name Name of the attribute or property for which to retrieve a
394    *  {@link ValueBinding}
395    *
396    * @exception NullPointerException if <code>name</code>
397    *  is <code>null</code>
398    * @exception IllegalArgumentException if <code>name</code> is not a valid
399    * attribute of this validator
400    */
401   public ValueBinding getValueBinding(String name)
402   {
403     return ValidatorUtils.getValueBinding(_facesBean, name);
404   }
405   
406   @Override
407   public boolean isTransient()
408   {
409     return (_transientValue);
410   }
411 
412 
413   @Override
414   public void setTransient(boolean transientValue)
415   {
416     _transientValue = transientValue;
417   }
418 
419   private FacesMessage _getNotInRangeMessage(
420       FacesContext context,
421       UIComponent component,
422       Object value,
423       Object min,
424       Object max)
425     {
426       Object msg   = _getRawNotInRangeMessageDetail();
427       Object label = ValidatorUtils.getComponentLabel(component);
428 
429       Object[] params = {label, value, min, max};
430 
431       return MessageFactory.getMessage(context, NOT_IN_RANGE_MESSAGE_ID,
432                                         msg, params, component);
433     }
434 
435 
436     
437     private Object _getRawNotInRangeMessageDetail()
438     {
439       return _facesBean.getRawProperty(_NOT_IN_RANGE_MESSAGE_DETAIL_KEY);
440     }
441 
442 
443     private FacesMessage _getMaximumMessage(
444       FacesContext context,
445       UIComponent component,
446       Object value,
447       Object max)
448     {
449 
450       Object msg   = _getRawMaximumMessageDetail();
451       Object label = ValidatorUtils.getComponentLabel(component);
452 
453       Object[] params = {label, value, max};
454 
455       return MessageFactory.getMessage(context,
456                                        MAXIMUM_MESSAGE_ID,
457                                        msg,
458                                        params,
459                                        component);
460     }
461 
462     private Object _getRawMaximumMessageDetail()
463     {
464       return _facesBean.getRawProperty(_MAXIMUM_MESSAGE_DETAIL_KEY);
465     }
466 
467     private FacesMessage _getMinimumMessage(
468       FacesContext context,
469       UIComponent component,
470       Object value,
471       Object min)
472     {
473       Object msg      = _getRawMinimumMessageDetail();
474       Object label    = ValidatorUtils.getComponentLabel(component);
475 
476       Object[] params = {label, value, min};
477 
478       return MessageFactory.getMessage(context, MINIMUM_MESSAGE_ID,
479                                        msg, params, component);
480     }
481 
482     private Object _getRawMinimumMessageDetail()
483     {
484       return _facesBean.getRawProperty(_MINIMUM_MESSAGE_DETAIL_KEY);
485     }
486 
487   private static final FacesBean.Type _TYPE = new FacesBean.Type();
488 
489   private static final PropertyKey _MINIMUM_KEY =
490     _TYPE.registerKey("minimum", Long.class);
491 
492   private static final PropertyKey _MAXIMUM_KEY =
493     _TYPE.registerKey("maximum", Long.class);
494 
495   private static final PropertyKey _MAXIMUM_MESSAGE_DETAIL_KEY =
496     _TYPE.registerKey("messageDetailMaximum", String.class);
497 
498   private static final PropertyKey _MINIMUM_MESSAGE_DETAIL_KEY =
499     _TYPE.registerKey("messageDetailMinimum", String.class);
500 
501   private static final PropertyKey _NOT_IN_RANGE_MESSAGE_DETAIL_KEY =
502     _TYPE.registerKey("messageDetailNotInRange", String.class);
503 
504   private static final PropertyKey  _HINT_MAXIMUM_KEY =
505     _TYPE.registerKey("hintMaximum", String.class);
506 
507   private static final PropertyKey  _HINT_MINIMUM_KEY =
508     _TYPE.registerKey("hintMinimum", String.class);
509 
510   private static final PropertyKey  _HINT_NOT_IN_RANGE =
511     _TYPE.registerKey("hintNotInRange", String.class);
512 
513   private FacesBean _facesBean = ValidatorUtils.getFacesBean(_TYPE);
514 
515   private boolean _transientValue = false;
516 }