org.apache.myfaces.trinidad.validator.LengthValidator Maven / Gradle / Ivy
Show all versions of trinidad-api Show documentation
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.myfaces.trinidad.validator;
import javax.el.ValueExpression;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFValidator;
import org.apache.myfaces.trinidad.bean.FacesBean;
import org.apache.myfaces.trinidad.bean.PropertyKey;
import org.apache.myfaces.trinidad.util.ComponentUtils;
import org.apache.myfaces.trinidad.util.MessageFactory;
/**
* Implementation for length of java.lang.String
values.
*
*/
@JSFValidator(configExcluded=true)
public class LengthValidator extends javax.faces.validator.LengthValidator
{
public static final String VALIDATOR_ID = "org.apache.myfaces.trinidad.Length";
/**
* The message identifier of the {@link javax.faces.application.FacesMessage}
* to be created if the maximum length check fails. The message format
* string for this message may optionally include {0}
,
* {1}
and {3}
placeholders,
* which will be replaced by user input, component label and configured
* maximum length.
*/
public static final String MAXIMUM_MESSAGE_ID =
"org.apache.myfaces.trinidad.validator.LengthValidator.MAXIMUM";
/**
* The message identifier of the {@link javax.faces.application.FacesMessage}
* to be created if the minimum length check fails. The message format
* string for this message may optionally include {0}
,
* {1}
and {2}
placeholders, which will be replaced
* by user input, component label and configured minimum length.
*/
public static final String MINIMUM_MESSAGE_ID =
"org.apache.myfaces.trinidad.validator.LengthValidator.MINIMUM";
/**
* The message identifier of the {@link javax.faces.application.FacesMessage}
* to be created if the maximum or minimum length check fails, and both
* the maximum and minimum lengths for this validator have been set.
* The message format string for this message may optionally include
* {0}
, {1}
, {2}
and {3}
* placeholders, which will be replaced by user input, component label,
* configured minimum length and configured maximum length.
*/
public static final String NOT_IN_RANGE_MESSAGE_ID =
"org.apache.myfaces.trinidad.validator.LengthValidator.NOT_IN_RANGE";
/**
* The message identifier of the {@link javax.faces.application.FacesMessage}
* to be created if the maximum and minimum lengths are the same,
* and the length check fails, and both
* the maximum and minimum values for this validator have been set.
* The message format string for this message may optionally include
* {0}
, {1}
, {2}
* placeholders, which will be replaced by user input, component label,
* configured minimum/maximum length.
*/
public static final String EXACT_MESSAGE_ID =
"org.apache.myfaces.trinidad.validator.LengthValidator.EXACT";
/**
* Construct a {@link Validator} with no preconfigured limits.
*/
public LengthValidator()
{
super();
}
/**
* Construct a {@link Validator} with the specified preconfigured
* limit.
*
* @param maximum Maximum length to allow
*/
public LengthValidator(int maximum)
{
super(maximum);
}
/**
* Construct a {@link Validator} with the specified preconfigured
* limits.
*
* @param maximum Maximum length to allow
* @param minimum Minimum length to allow
*
*/
public LengthValidator(int maximum, int minimum)
{
super(maximum, minimum);
}
/**
* Return the maximum length to be enforced by this {@link
* Validator} or null if it has not been
* set.
*/
@JSFProperty
@Override
public int getMaximum()
{
Object maxInt = _facesBean.getProperty(_MAXIMUM_KEY);
return ComponentUtils.resolveInteger(maxInt);
}
/**
* Set the maximum length to be enforced by this {@link Validator}.
*
* @param maximum The new maximum length
*
*/
@Override
public void setMaximum(int maximum)
{
_facesBean.setProperty(_MAXIMUM_KEY, Integer.valueOf(maximum));
}
/**
* Return the minimum length to be enforced by this {@link
* Validator}, or null if it has not been
* set.
*/
@JSFProperty
@Override
public int getMinimum()
{
Object minInt = _facesBean.getProperty(_MINIMUM_KEY);
return ComponentUtils.resolveInteger(minInt);
}
/**
* Set the minimum length to be enforced by this {@link Validator}.
*
* @param minimum The new minimum length
*
*/
@Override
public void setMinimum(int minimum)
{
_facesBean.setProperty(_MINIMUM_KEY, Integer.valueOf(minimum));
}
/**
* Custom error message to be used, for creating detail part of the
* {@link FacesMessage}, when input length exceeds the maximum length set.
* Overrides detail message identified by message id {@link #MAXIMUM_MESSAGE_ID}
* @param maximumMessageDetail Custom error message.
*/
public void setMessageDetailMaximum(String maximumMessageDetail)
{
_facesBean.setProperty(_MAXIMUM_MESSAGE_DETAIL_KEY, maximumMessageDetail);
}
/**
* Return custom detail error message that was set for creating {@link FacesMessage},
* for cases where input length exceeds the maximum
length set.
* @return Custom error message.
* @see #setMessageDetailMaximum(String)
*/
@JSFProperty
public String getMessageDetailMaximum()
{
Object maxMsgDet = _facesBean.getProperty(_MAXIMUM_MESSAGE_DETAIL_KEY);
return ComponentUtils.resolveString(maxMsgDet);
}
/**
* Custom error message to be used, for creating detail part of the
* {@link FacesMessage}, when input length is less the set
* minimum
length.
* Overrides detail message identified by message id {@link #MINIMUM_MESSAGE_ID}
* @param minimumMessageDetail Custom error message.
*/
public void setMessageDetailMinimum(String minimumMessageDetail)
{
_facesBean.setProperty(_MINIMUM_MESSAGE_DETAIL_KEY, minimumMessageDetail);
}
/**
* Return custom detail error message that was set for creating {@link FacesMessage},
* for cases where, input length is less than the minimum
length set.
* @return Custom error message.
* @see #setMessageDetailMinimum(String)
*/
@JSFProperty
public String getMessageDetailMinimum()
{
Object minMsgDet = _facesBean.getProperty(_MINIMUM_MESSAGE_DETAIL_KEY);
return ComponentUtils.resolveString(minMsgDet);
}
/**
* Custom error message to be used, for creating detail part of the
* {@link FacesMessage}, when input length is not with in the range,
* when minimum
and maximum
is set.
* Overrides detail message identified by message id {@link #NOT_IN_RANGE_MESSAGE_ID}
* @param notInRangeMessageDetail Custom error message.
*/
public void setMessageDetailNotInRange(String notInRangeMessageDetail)
{
_facesBean.setProperty(_NOT_IN_RANGE_MESSAGE_DETAIL_KEY, notInRangeMessageDetail);
}
/**
* Return custom detail error message that was set for creating {@link FacesMessage},
* for cases where, input length exceeds the maximum
length and is
* less than the minimum
length set.
* @return Custom error message.
* @see #setMessageDetailNotInRange(String)
*/
@JSFProperty
public String getMessageDetailNotInRange()
{
Object notInRngMsg = _facesBean.getProperty(_NOT_IN_RANGE_MESSAGE_DETAIL_KEY);
return ComponentUtils.resolveString(notInRngMsg);
}
/**
* Custom error message to be used, for creating detail part of the
* {@link FacesMessage},
* for cases where the maximum and minimum lengths are the same, and
* the input length does not match.
* Overrides detail message identified by message id {@link #EXACT_MESSAGE_ID}
* @param exactMessageDetail Custom error message.
*/
public void setMessageDetailExact(String exactMessageDetail)
{
_facesBean.setProperty(_EXACT_MESSAGE_DETAIL_KEY, exactMessageDetail);
}
/**
*
Return custom detail error message that was set for creating {@link FacesMessage},
* for cases where the maximum and minimum lengths are the same, and
* the input length does not match.
* @return Custom error message.
* @see #setMessageDetailExact(String)
*/
@JSFProperty
public String getMessageDetailExact()
{
Object msg = _facesBean.getProperty(_EXACT_MESSAGE_DETAIL_KEY);
return ComponentUtils.resolveString(msg);
}
/**
* Custom hint maximum message.
* Overrides default hint message
* @param hintMaximum Custom hint message.
*/
public void setHintMaximum(String hintMaximum)
{
_facesBean.setProperty(_HINT_MAXIMUM_KEY, hintMaximum);
}
/**
* Return custom hint maximum message.
* @return Custom hint message.
* @see #setHintMaximum(String)
*/
@JSFProperty(tagExcluded=true)
public String getHintMaximum()
{
Object obj = _facesBean.getProperty(_HINT_MAXIMUM_KEY);
return ComponentUtils.resolveString(obj);
}
/**
* Custom hint minimum message.
* Overrides default hint message
* @param hintMinimum Custom hint message.
*/
public void setHintMinimum(String hintMinimum)
{
_facesBean.setProperty(_HINT_MINIMUM_KEY, hintMinimum);
}
/**
* Return custom hint minimum message.
* @return Custom hint message.
* @see #setHintMinimum(String)
*/
@JSFProperty(tagExcluded=true)
public String getHintMinimum()
{
Object obj = _facesBean.getProperty(_HINT_MINIMUM_KEY);
return ComponentUtils.resolveString(obj);
}
/**
* Custom hint notInRange message.
* Overrides default hint message
* @param hintNotInRange Custom hint message.
*/
public void setHintNotInRange(String hintNotInRange)
{
_facesBean.setProperty(_HINT_NOT_IN_RANGE, hintNotInRange);
}
/**
* Return custom hint notInRange message.
* @return Custom hint message.
* @see #setHintNotInRange
*/
@JSFProperty(tagExcluded=true)
public String getHintNotInRange()
{
Object obj = _facesBean.getProperty(_HINT_NOT_IN_RANGE);
return ComponentUtils.resolveString(obj);
}
/**
* Custom hint exact message.
* Overrides default hint message
* @param hintExact Custom hint message.
*/
public void setHintExact(String hintExact)
{
_facesBean.setProperty(_HINT_EXACT, hintExact);
}
/**
* Return custom hint exact message.
* @return Custom hint message.
* @see #setHintExact
*/
@JSFProperty(tagExcluded=true)
public String getHintExact()
{
Object obj = _facesBean.getProperty(_HINT_EXACT);
return ComponentUtils.resolveString(obj);
}
@Override
public void validate(
FacesContext context,
UIComponent component,
Object value
) throws ValidatorException
{
if (isDisabled())
return;
if ((context == null) || (component == null))
{
throw new NullPointerException();
}
if(value != null)
{
String theValue = (value instanceof String)? (String)value : value.toString();
int max = getMaximum();
int min = getMinimum();
// Skip validating empty field values, even if a minimum length is specified.
// Forcing minimum length validation on empty fields will break the use-case where the
// app would like a field to remain optional, but in case some value is entered, it should
// adhere to some min/max length rules. For ex: A "pin code" field that is optional.
if (theValue.isEmpty())
return;
int length = theValue.length();
// range validation
if(isMaximumSet() && isMinimumSet())
{
if(lengthmax)
{
throw new ValidatorException(
_getNotInRangeMessage(context, component, value, min, max));
}
}
// too short
if(isMinimumSet())
{
if (length < min)
{
throw new ValidatorException(
_getMinimumMessage(context, component, value, min));
}
}
// too long
if(isMaximumSet())
{
if (length > max)
{
throw new ValidatorException(
_getMaximumMessage(context, component, value, max));
}
}
}
}
// StateHolder Methods
@Override
public Object saveState(FacesContext context)
{
return _facesBean.saveState(context);
}
@Override
public void restoreState(FacesContext context, Object state)
{
_facesBean.restoreState(context, state);
}
/**
* Set the {@link ValueExpression} used to calculate the value for the
* specified attribute if any.
*
* @param name Name of the attribute for which to set a {@link ValueExpression}
* @param expression The {@link ValueExpression} to set, or null
* to remove any currently set {@link ValueExpression}
*
* @exception NullPointerException if name
* is null
* @exception IllegalArgumentException if name
is not a valid
* attribute of this converter
*/
public void setValueExpression(String name, ValueExpression expression)
{
ValidatorUtils.setValueExpression(_facesBean, name, expression) ;
}
/**
* Return the {@link ValueExpression} used to calculate the value for the
* specified attribute name, if any.
*
* @param name Name of the attribute or property for which to retrieve a
* {@link ValueExpression}
*
* @exception NullPointerException if name
* is null
* @exception IllegalArgumentException if name
is not a valid
* attribute of this converter
*/
public ValueExpression getValueExpression(String name)
{
return ValidatorUtils.getValueExpression(_facesBean, name);
}
/**
* Set the {@link ValueBinding} used to calculate the value for the
* specified attribute if any.
*
* @param name Name of the attribute for which to set a {@link ValueBinding}
* @param binding The {@link ValueBinding} to set, or null
* to remove any currently set {@link ValueBinding}
*
* @exception NullPointerException if name
* is null
* @exception IllegalArgumentException if name
is not a valid
* attribute of this validator
* @deprecated
*/
public void setValueBinding(String name, ValueBinding binding)
{
ValidatorUtils.setValueBinding(_facesBean, name, binding) ;
}
/**
* Return the {@link ValueBinding} used to calculate the value for the
* specified attribute name, if any.
*
* @param name Name of the attribute or property for which to retrieve a
* {@link ValueBinding}
*
* @exception NullPointerException if name
* is null
* @exception IllegalArgumentException if name
is not a valid
* attribute of this validator
* @deprecated
*/
public ValueBinding getValueBinding(String name)
{
return ValidatorUtils.getValueBinding(_facesBean, name);
}
@JSFProperty(istransient=true, tagExcluded=true)
@Override
public boolean isTransient()
{
return (_transientValue);
}
@Override
public void setTransient(boolean transientValue)
{
_transientValue = transientValue;
}
@Override
public boolean equals(Object otherObj)
{
if (!(otherObj instanceof LengthValidator))
{
return false;
}
LengthValidator other = (LengthValidator) otherObj;
return ((this.getMaximum() == other.getMaximum())
&& (this.getMinimum() == other.getMinimum())
&& (this.isMinimumSet() == other.isMinimumSet())
&& (this.isMaximumSet() == other.isMaximumSet())
&& (this.isDisabled() == other.isDisabled())
&& (this.isTransient() == other.isTransient()));
}
@Override
public int hashCode()
{
int result = 17;
Object msgDetExact = getMessageDetailExact();
Object maxMsgDet = getMessageDetailMaximum();
Object minMsgDet = getMessageDetailMinimum();
Object notInRangeMsgDet = getMessageDetailNotInRange();
result = 37 * result + (isDisabled() ? 1 : 0);
result = 37 * result + (isTransient() ? 0 : 1);
result = 37 * result + (isMaximumSet() ? 0 : 1);
result = 37 * result + (isMinimumSet() ? 0 : 1);
result = 37 * result + Integer.valueOf(getMinimum()).hashCode();
result = 37 * result + Integer.valueOf(getMaximum()).hashCode();
result = 37 * result + ( msgDetExact == null ? 0 : msgDetExact.hashCode());
result = 37 * result + ( maxMsgDet == null ? 0 : maxMsgDet.hashCode());
result = 37 * result + ( minMsgDet == null ? 0 : minMsgDet.hashCode());
result = 37 * result + ( notInRangeMsgDet == null ? 0 : notInRangeMsgDet.hashCode());
return result;
}
/**
* Return whether it is disabled.
* @return true if it's disabled and false if it's enabled.
*/
public void setDisabled(boolean isDisabled)
{
_facesBean.setProperty(_DISABLED_KEY, Boolean.valueOf(isDisabled));
}
/**
* Return whether it is disabled.
* @return true if it's disabled and false if it's enabled.
*/
public boolean isDisabled()
{
Boolean disabled = (Boolean) _facesBean.getProperty(_DISABLED_KEY);
return (disabled != null) ? disabled.booleanValue() : false;
}
protected boolean isMaximumSet()
{
return _facesBean.getProperty(_MAXIMUM_KEY) != null;
}
protected boolean isMinimumSet()
{
return _facesBean.getProperty(_MINIMUM_KEY) != null;
}
private FacesMessage _getNotInRangeMessage(
FacesContext context,
UIComponent component,
Object value,
Object min,
Object max)
{
if (min.equals(max))
return _getExactMessage(context, component, value, min);
Object msg = _getRawNotInRangeMessageDetail();
Object label = ValidatorUtils.getComponentLabel(component);
Object[] params = {label, value, min, max};
return MessageFactory.getMessage(context, NOT_IN_RANGE_MESSAGE_ID,
msg, params, component);
}
private Object _getRawNotInRangeMessageDetail()
{
return _facesBean.getRawProperty(_NOT_IN_RANGE_MESSAGE_DETAIL_KEY);
}
private FacesMessage _getExactMessage(
FacesContext context,
UIComponent component,
Object value,
Object minMax)
{
Object msg = _getRawExactMessageDetail();
Object label = ValidatorUtils.getComponentLabel(component);
Object[] params = {label, value, minMax};
return MessageFactory.getMessage(context, EXACT_MESSAGE_ID,
msg, params, component);
}
private Object _getRawExactMessageDetail()
{
return _facesBean.getRawProperty(_EXACT_MESSAGE_DETAIL_KEY);
}
private FacesMessage _getMaximumMessage(
FacesContext context,
UIComponent component,
Object value,
Object max)
{
Object msg = _getRawMaximumMessageDetail();
Object label = ValidatorUtils.getComponentLabel(component);
Object[] params = {label, value, max};
return MessageFactory.getMessage(context,
MAXIMUM_MESSAGE_ID,
msg,
params,
component);
}
private Object _getRawMaximumMessageDetail()
{
return _facesBean.getRawProperty(_MAXIMUM_MESSAGE_DETAIL_KEY);
}
private FacesMessage _getMinimumMessage(
FacesContext context,
UIComponent component,
Object value,
Object min)
{
Object msg = _getRawMinimumMessageDetail();
Object label = ValidatorUtils.getComponentLabel(component);
Object[] params = {label, value, min};
return MessageFactory.getMessage(context, MINIMUM_MESSAGE_ID,
msg, params, component);
}
private Object _getRawMinimumMessageDetail()
{
return _facesBean.getRawProperty(_MINIMUM_MESSAGE_DETAIL_KEY);
}
private static final FacesBean.Type _TYPE = new FacesBean.Type();
// Default is false
private static final PropertyKey _DISABLED_KEY =
_TYPE.registerKey("disabled",
Boolean.class,
Boolean.FALSE);
// Default is zero, not MIN_VALUE
private static final PropertyKey _MINIMUM_KEY =
_TYPE.registerKey("minimum",
Integer.class,
// Don't rely on autoboxing: there's a method overload
Integer.valueOf(0));
// FIXME: the default of the superclass is 0, not MAX_VALUE
private static final PropertyKey _MAXIMUM_KEY =
_TYPE.registerKey("maximum", Integer.class,
// Don't rely on autoboxing: there's a method overload
Integer.valueOf(0));
private static final PropertyKey _MAXIMUM_MESSAGE_DETAIL_KEY =
_TYPE.registerKey("messageDetailMaximum", String.class);
private static final PropertyKey _MINIMUM_MESSAGE_DETAIL_KEY =
_TYPE.registerKey("messageDetailMinimum", String.class);
private static final PropertyKey _NOT_IN_RANGE_MESSAGE_DETAIL_KEY =
_TYPE.registerKey("messageDetailNotInRange", String.class);
private static final PropertyKey _EXACT_MESSAGE_DETAIL_KEY =
_TYPE.registerKey("messageDetailExact", String.class);
private static final PropertyKey _HINT_MAXIMUM_KEY =
_TYPE.registerKey("hintMaximum", String.class);
private static final PropertyKey _HINT_MINIMUM_KEY =
_TYPE.registerKey("hintMinimum", String.class);
private static final PropertyKey _HINT_NOT_IN_RANGE =
_TYPE.registerKey("hintNotInRange", String.class);
private static final PropertyKey _HINT_EXACT =
_TYPE.registerKey("hintExact", String.class);
private FacesBean _facesBean = ValidatorUtils.getFacesBean(_TYPE);
private boolean _transientValue = false;
}