com.vaadin.data.validator.RangeValidator Maven / Gradle / Ivy
/*
* 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.Comparator;
import java.util.Objects;
import com.vaadin.data.ValidationResult;
import com.vaadin.data.ValueContext;
/**
* Verifies that a value is within the given range.
*
* @param
* the type to validate
* @author Vaadin Ltd.
* @since 8.0
*/
public class RangeValidator extends AbstractValidator {
private T minValue = null;
private T maxValue = null;
private boolean minValueIncluded = true;
private boolean maxValueIncluded = true;
private final Comparator super T> comparator;
/**
* Creates a new range validator of the given type. Passing null to either
* {@code minValue} or {@code maxValue} means there is no limit in that
* direction. Both limits may be null; this can be useful if the limits are
* resolved programmatically. The result of passing null to {@code apply}
* depends on the given comparator.
*
* @param errorMessage
* the error message to return if validation fails, not null
* @param comparator
* the comparator to compare with, not null
* @param minValue
* the least value of the accepted range or null for no limit
* @param maxValue
* the greatest value of the accepted range or null for no limit
*/
public RangeValidator(String errorMessage, Comparator super T> comparator,
T minValue, T maxValue) {
super(errorMessage);
Objects.requireNonNull(comparator, "comparator cannot be null");
this.minValue = minValue;
this.maxValue = maxValue;
this.minValueIncluded = minValue != null;
this.maxValueIncluded = maxValue != null;
this.comparator = comparator;
}
/**
* Returns a {@code RangeValidator} comparing values of a {@code Comparable}
* type using their natural order. Passing null to either
* {@code minValue} or {@code maxValue} means there is no limit in that
* direction. Both limits may be null; this can be useful if the limits are
* resolved programmatically.
*
* Null is considered to be less than any non-null value. This means null
* never passes validation if a minimum value is specified.
*
* @param
* the {@code Comparable} value type
* @param errorMessage
* the error message to return if validation fails, not null
* @param minValue
* the least value of the accepted range or null for no limit
* @param maxValue
* the greatest value of the accepted range or null for no limit
* @return the new validator
*/
public static > RangeValidator of(
String errorMessage, C minValue, C maxValue) {
return new RangeValidator<>(errorMessage,
Comparator.nullsFirst(Comparator.naturalOrder()), minValue,
maxValue);
}
/**
* Returns {@code Result.ok} if the value is within the specified bounds,
* {@code Result.error} otherwise. If null is passed to {@code apply}, the
* behavior depends on the used comparator.
*/
@Override
public ValidationResult apply(T value, ValueContext context) {
return toResult(value, isValid(value));
}
/**
* Returns whether the minimum value is part of the accepted range.
*
* @return true if the minimum value is part of the range, false otherwise
*/
public boolean isMinValueIncluded() {
return minValueIncluded;
}
/**
* Sets whether the minimum value is part of the accepted range.
*
* @param minValueIncluded
* true if the minimum value should be part of the range, false
* otherwise
*/
public void setMinValueIncluded(boolean minValueIncluded) {
this.minValueIncluded = minValueIncluded;
}
/**
* Returns whether the maximum value is part of the accepted range.
*
* @return true if the maximum value is part of the range, false otherwise
*/
public boolean isMaxValueIncluded() {
return maxValueIncluded;
}
/**
* Sets whether the maximum value is part of the accepted range.
*
* @param maxValueIncluded
* true if the maximum value should be part of the range, false
* otherwise
*/
public void setMaxValueIncluded(boolean maxValueIncluded) {
this.maxValueIncluded = maxValueIncluded;
}
/**
* Returns the minimum value of the range.
*
* @return the minimum value
*/
public T getMinValue() {
return minValue;
}
/**
* Sets the minimum value of the range. Use
* {@link #setMinValueIncluded(boolean)} to control whether this value is
* part of the range or not.
*
* @param minValue
* the minimum value
*/
public void setMinValue(T minValue) {
this.minValue = minValue;
}
/**
* Gets the maximum value of the range.
*
* @return the maximum value
*/
public T getMaxValue() {
return maxValue;
}
/**
* Sets the maximum value of the range. Use
* {@link #setMaxValueIncluded(boolean)} to control whether this value is
* part of the range or not.
*
* @param maxValue
* the maximum value
*/
public void setMaxValue(T maxValue) {
this.maxValue = maxValue;
}
@Override
public String toString() {
T min = getMinValue();
T max = getMaxValue();
return String.format("%s %c%s, %s%c", getClass().getSimpleName(),
isMinValueIncluded() ? '[' : '(', min != null ? min : "-∞",
max != null ? max : "∞", isMaxValueIncluded() ? ']' : ')');
}
/**
* Returns whether the given value lies in the valid range.
*
* @param value
* the value to validate
* @return true if the value is valid, false otherwise
*/
protected boolean isValid(T value) {
if (value == null) {
return true;
}
if (getMinValue() != null) {
int result = comparator.compare(value, getMinValue());
if (result < 0) {
return false;
} else if (result == 0 && !isMinValueIncluded()) {
return false;
}
}
if (getMaxValue() != null) {
int result = comparator.compare(value, getMaxValue());
if (result > 0) {
return false;
} else if (result == 0 && !isMaxValueIncluded()) {
return false;
}
}
return true;
}
}