com.vaadin.data.validator.CompositeValidator Maven / Gradle / Ivy
/*
* Vaadin Framework 7
*
* Copyright (C) 2000-2024 Vaadin Ltd
*
* This program is available under Vaadin Commercial License and Service Terms.
*
* See for the full
* license.
*/
package com.vaadin.data.validator;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import com.vaadin.data.Validator;
/**
* The CompositeValidator
allows you to chain (compose) many
* validators to validate one field. The contained validators may be required to
* all validate the value to validate or it may be enough that one contained
* validator validates the value. This behaviour is controlled by the modes
* AND
and OR
.
*
* @author Vaadin Ltd.
* @since 3.0
*/
@SuppressWarnings("serial")
public class CompositeValidator implements Validator {
public enum CombinationMode {
/**
* The validators are combined with AND
clause: validity of
* the composite implies validity of the all validators it is composed
* of must be valid.
*/
AND,
/**
* The validators are combined with OR
clause: validity of
* the composite implies that some of validators it is composed of must
* be valid.
*/
OR;
}
/**
* @deprecated As of 7.0, use {@link CombinationMode#AND} instead
*/
@Deprecated
public static final CombinationMode MODE_AND = CombinationMode.AND;
/**
* @deprecated As of 7.0, use {@link CombinationMode#OR} instead
*/
@Deprecated
public static final CombinationMode MODE_OR = CombinationMode.OR;
private String errorMessage;
/**
* Operation mode.
*/
private CombinationMode mode = CombinationMode.AND;
/**
* List of contained validators.
*/
private final List validators = new LinkedList();
/**
* Construct a composite validator in AND
mode without error
* message.
*/
public CompositeValidator() {
this(CombinationMode.AND, "");
}
/**
* Constructs a composite validator in given mode.
*
* @param mode
* @param errorMessage
*/
public CompositeValidator(CombinationMode mode, String errorMessage) {
setErrorMessage(errorMessage);
setMode(mode);
}
/**
* Validates the given value.
*
* The value is valid, if:
*
* MODE_AND
: All of the sub-validators are valid
* MODE_OR
: Any of the sub-validators are valid
*
*
* If the value is invalid, validation error is thrown. If the error message
* is set (non-null), it is used. If the error message has not been set, the
* first error occurred is thrown.
*
*
* @param value
* the value to check.
* @throws Validator.InvalidValueException
* if the value is not valid.
*/
@Override
public void validate(Object value) throws Validator.InvalidValueException {
switch (mode) {
case AND:
for (Validator validator : validators) {
validator.validate(value);
}
return;
case OR:
Validator.InvalidValueException first = null;
for (Validator v : validators) {
try {
v.validate(value);
return;
} catch (final Validator.InvalidValueException e) {
if (first == null) {
first = e;
}
}
}
if (first == null) {
return;
}
final String em = getErrorMessage();
if (em != null) {
throw new Validator.InvalidValueException(em);
} else {
throw first;
}
}
}
/**
* Gets the mode of the validator.
*
* @return Operation mode of the validator: {@link CombinationMode#AND} or
* {@link CombinationMode#OR}.
*/
public final CombinationMode getMode() {
return mode;
}
/**
* Sets the mode of the validator. The valid modes are:
*
* - {@link CombinationMode#AND} (default)
*
- {@link CombinationMode#OR}
*
*
* @param mode
* the mode to set.
*/
public void setMode(CombinationMode mode) {
if (mode == null) {
throw new IllegalArgumentException(
"The validator can't be set to null");
}
this.mode = mode;
}
/**
* Gets the error message for the composite validator. If the error message
* is null, original error messages of the sub-validators are used instead.
*/
public String getErrorMessage() {
if (errorMessage != null) {
return errorMessage;
}
// TODO Return composite error message
return null;
}
/**
* Adds validator to the interface.
*
* @param validator
* the Validator object which performs validation checks on this
* set of data field values.
*/
public void addValidator(Validator validator) {
if (validator == null) {
return;
}
validators.add(validator);
}
/**
* Removes a validator from the composite.
*
* @param validator
* the Validator object which performs validation checks on this
* set of data field values.
*/
public void removeValidator(Validator validator) {
validators.remove(validator);
}
/**
* Gets sub-validators by class.
*
*
* If the component contains directly or recursively (it contains another
* composite containing the validator) validators compatible with given type
* they are returned. This only applies to AND
mode composite
* validators.
*
*
*
* If the validator is in OR
mode or does not contain any
* validators of given type null is returned.
*
*
* @param validatorType
* The type of validators to return
*
* @return Collection of validators compatible with given type
* that must apply or null if none found.
*/
public Collection getSubValidators(Class validatorType) {
if (mode != CombinationMode.AND) {
return null;
}
final HashSet found = new HashSet();
for (Validator v : validators) {
if (validatorType.isAssignableFrom(v.getClass())) {
found.add(v);
}
if (v instanceof CompositeValidator
&& ((CompositeValidator) v).getMode() == MODE_AND) {
final Collection c = ((CompositeValidator) v)
.getSubValidators(validatorType);
if (c != null) {
found.addAll(c);
}
}
}
return found.isEmpty() ? null : found;
}
/**
* Sets the message to be included in the exception in case the value does
* not validate. The exception message is typically shown to the end user.
*
* @param errorMessage
* the error message.
*/
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
}