Change-Id: I6e4a56855f78595975b645a08390fb56e0e52ef9tags/8.0.0.alpha1
@@ -0,0 +1,85 @@ | |||
/* | |||
* Copyright 2000-2014 Vaadin Ltd. | |||
* | |||
* Licensed 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 com.vaadin.data.validator; | |||
import java.util.Objects; | |||
import java.util.function.Function; | |||
import com.vaadin.data.Result; | |||
import com.vaadin.data.Validator; | |||
/** | |||
* An abstract base class for typed validators. | |||
* | |||
* @param <T> | |||
* The value type | |||
* @author Vaadin Ltd. | |||
* @since 8.0 | |||
*/ | |||
public abstract class AbstractValidator<T> implements Validator<T> { | |||
private Function<T, String> messageProvider; | |||
/** | |||
* Constructs a validator with the given error message. The substring "{0}" | |||
* is replaced by the value that failed validation. | |||
* | |||
* @param errorMessage | |||
* the message to be included in a failed result, not null | |||
*/ | |||
protected AbstractValidator(String errorMessage) { | |||
Objects.requireNonNull(errorMessage, "error message cannot be null"); | |||
this.messageProvider = value -> errorMessage.replace("{0}", | |||
String.valueOf(value)); | |||
} | |||
/** | |||
* Returns the error message for the given value. | |||
* | |||
* @param value | |||
* an invalid value | |||
* @return the formatted error message | |||
*/ | |||
protected String getMessage(T value) { | |||
return messageProvider.apply(value); | |||
} | |||
/** | |||
* A helper method for creating a {@code Result} from a value and a validity | |||
* flag. If the flag is true, returns {@code Result.ok}, otherwise yields | |||
* {@code Result.error} bearing the error message returned by | |||
* {@link #getMessage(T)}. | |||
* <p> | |||
* For instance, the following {@code apply} method only accepts even | |||
* numbers: | |||
* | |||
* <pre> | |||
* @Override | |||
* public Result<T> apply(Integer value) { | |||
* return toResult(value, value % 2 == 0); | |||
* } | |||
* </pre> | |||
* | |||
* @param value | |||
* the validated value | |||
* @param isValid | |||
* whether the value is valid or not | |||
* @return the validation result | |||
*/ | |||
protected Result<T> toResult(T value, boolean isValid) { | |||
return isValid ? Result.ok(value) : Result.error(getMessage(value)); | |||
} | |||
} |
@@ -0,0 +1,195 @@ | |||
/* | |||
* Copyright 2000-2014 Vaadin Ltd. | |||
* | |||
* Licensed 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 com.vaadin.data.validator; | |||
import java.util.Locale; | |||
import java.util.Objects; | |||
import java.util.Set; | |||
import java.util.function.BinaryOperator; | |||
import javax.validation.ConstraintViolation; | |||
import javax.validation.MessageInterpolator.Context; | |||
import javax.validation.Validation; | |||
import javax.validation.ValidatorFactory; | |||
import javax.validation.metadata.ConstraintDescriptor; | |||
import com.vaadin.data.Result; | |||
import com.vaadin.data.Validator; | |||
/** | |||
* A {@code Validator} using the JSR-303 (javax.validation) annotation-based | |||
* bean validation mechanism. Values passed to this validator are compared | |||
* against the constraints, if any, specified by annotations on the | |||
* corresponding bean property. | |||
* <p> | |||
* Note that a JSR-303 implementation (e.g. Hibernate Validator or Apache Bean | |||
* Validation - formerly agimatec validation) must be present on the project | |||
* classpath when using bean validation. | |||
* | |||
* @author Petri Hakala | |||
* @author Vaadin Ltd. | |||
* | |||
* @since 8.0 | |||
*/ | |||
public class BeanValidator implements Validator<Object> { | |||
private static final long serialVersionUID = 1L; | |||
private static ValidatorFactory factory; | |||
private String propertyName; | |||
private Class<?> beanType; | |||
private Locale locale; | |||
/** | |||
* Creates a new JSR-303 {@code BeanValidator} that validates values of the | |||
* specified property. Localizes validation messages using the | |||
* {@linkplain Locale#getDefault() default locale}. | |||
* | |||
* @param beanType | |||
* the bean type declaring the property, not null | |||
* @param propertyName | |||
* the property to validate, not null | |||
*/ | |||
public BeanValidator(Class<?> beanType, String propertyName) { | |||
this(beanType, propertyName, Locale.getDefault()); | |||
} | |||
/** | |||
* Creates a new JSR-303 {@code BeanValidator} that validates values of the | |||
* specified property. Localizes validation messages using the given locale. | |||
* | |||
* @param beanType | |||
* the bean class declaring the property, not null | |||
* @param propertyName | |||
* the property to validate, not null | |||
* @param locale | |||
* the locale to use, not null | |||
*/ | |||
public BeanValidator(Class<?> beanType, String propertyName, | |||
Locale locale) { | |||
Objects.requireNonNull(beanType, "bean class cannot be null"); | |||
Objects.requireNonNull(propertyName, "property name cannot be null"); | |||
this.beanType = beanType; | |||
this.propertyName = propertyName; | |||
setLocale(locale); | |||
} | |||
/** | |||
* Validates the given value as if it were the value of the bean property | |||
* configured for this validator. Returns {@code Result.ok} if there are no | |||
* JSR-303 constraint violations, a {@code Result.error} of chained | |||
* constraint violation messages otherwise. | |||
* <p> | |||
* Null values are accepted unless the property has an {@code @NotNull} | |||
* annotation or equivalent. | |||
*/ | |||
@Override | |||
public Result<Object> apply(final Object value) { | |||
Set<? extends ConstraintViolation<?>> violations = getJavaxBeanValidator() | |||
.validateValue(beanType, propertyName, value); | |||
BinaryOperator<Result<Object>> accumulator = (result1, | |||
result2) -> result1.flatMap(val -> result2); | |||
return violations.stream().map(v -> Result.error(getMessage(v))) | |||
.reduce(Result.ok(value), accumulator); | |||
} | |||
/** | |||
* Returns the locale used for validation error messages. | |||
* | |||
* @return the locale used for error messages | |||
*/ | |||
public Locale getLocale() { | |||
return locale; | |||
} | |||
@Override | |||
public String toString() { | |||
return String.format("%s[%s.%s]", getClass().getSimpleName(), | |||
beanType.getSimpleName(), propertyName); | |||
} | |||
/** | |||
* Returns the underlying JSR-303 bean validator factory used. A factory is | |||
* created using {@link Validation} if necessary. | |||
* | |||
* @return the validator factory to use | |||
*/ | |||
protected static ValidatorFactory getJavaxBeanValidatorFactory() { | |||
if (factory == null) { | |||
factory = Validation.buildDefaultValidatorFactory(); | |||
} | |||
return factory; | |||
} | |||
/** | |||
* Returns a shared JSR-303 validator instance to use. | |||
* | |||
* @return the validator to use | |||
*/ | |||
protected javax.validation.Validator getJavaxBeanValidator() { | |||
return getJavaxBeanValidatorFactory().getValidator(); | |||
} | |||
/** | |||
* Returns the interpolated error message for the given constraint violation | |||
* using the locale specified for this validator. | |||
* | |||
* @param v | |||
* the constraint violation | |||
* @return the localized error message | |||
*/ | |||
protected String getMessage(ConstraintViolation<?> v) { | |||
return getJavaxBeanValidatorFactory().getMessageInterpolator() | |||
.interpolate(v.getMessageTemplate(), createContext(v), locale); | |||
} | |||
/** | |||
* Creates a simple message interpolation context based on the given | |||
* constraint violation. | |||
* | |||
* @param v | |||
* the constraint violation | |||
* @return the message interpolation context | |||
*/ | |||
protected Context createContext(ConstraintViolation<?> v) { | |||
return new Context() { | |||
@Override | |||
public ConstraintDescriptor<?> getConstraintDescriptor() { | |||
return v.getConstraintDescriptor(); | |||
} | |||
@Override | |||
public Object getValidatedValue() { | |||
return v.getInvalidValue(); | |||
} | |||
}; | |||
} | |||
/** | |||
* Sets the locale used for validation error messages. Revalidation is not | |||
* automatically triggered by setting the locale. | |||
* | |||
* @param locale | |||
* the locale to use for error messages, not null | |||
*/ | |||
private void setLocale(Locale locale) { | |||
Objects.requireNonNull(locale, "locale cannot be null"); | |||
this.locale = locale; | |||
} | |||
} |
@@ -0,0 +1,51 @@ | |||
/* | |||
* Copyright 2000-2014 Vaadin Ltd. | |||
* | |||
* Licensed 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 com.vaadin.data.validator; | |||
import java.math.BigDecimal; | |||
import java.util.Comparator; | |||
/** | |||
* Validator for validating that an {@link BigDecimal} is inside a given range. | |||
* | |||
* @author Vaadin Ltd. | |||
* @since 8.0 | |||
*/ | |||
@SuppressWarnings("serial") | |||
public class BigDecimalRangeValidator extends RangeValidator<BigDecimal> { | |||
/** | |||
* Creates a validator for checking that an BigDecimal is within a given | |||
* range. | |||
* | |||
* By default the range is inclusive i.e. both minValue and maxValue are | |||
* valid values. Use {@link #setMinValueIncluded(boolean)} or | |||
* {@link #setMaxValueIncluded(boolean)} to change it. | |||
* | |||
* | |||
* @param errorMessage | |||
* the message to display in case the value does not validate. | |||
* @param minValue | |||
* The minimum value to accept or null for no limit | |||
* @param maxValue | |||
* The maximum value to accept or null for no limit | |||
*/ | |||
public BigDecimalRangeValidator(String errorMessage, BigDecimal minValue, | |||
BigDecimal maxValue) { | |||
super(errorMessage, Comparator.naturalOrder(), minValue, maxValue); | |||
} | |||
} |
@@ -0,0 +1,51 @@ | |||
/* | |||
* Copyright 2000-2014 Vaadin Ltd. | |||
* | |||
* Licensed 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 com.vaadin.data.validator; | |||
import java.math.BigInteger; | |||
import java.util.Comparator; | |||
/** | |||
* Validator for validating that an {@link BigInteger} is inside a given range. | |||
* | |||
* @author Vaadin Ltd. | |||
* @since 8.0 | |||
*/ | |||
@SuppressWarnings("serial") | |||
public class BigIntegerRangeValidator extends RangeValidator<BigInteger> { | |||
/** | |||
* Creates a validator for checking that an BigInteger is within a given | |||
* range. | |||
* | |||
* By default the range is inclusive i.e. both minValue and maxValue are | |||
* valid values. Use {@link #setMinValueIncluded(boolean)} or | |||
* {@link #setMaxValueIncluded(boolean)} to change it. | |||
* | |||
* | |||
* @param errorMessage | |||
* the message to display in case the value does not validate. | |||
* @param minValue | |||
* The minimum value to accept or null for no limit | |||
* @param maxValue | |||
* The maximum value to accept or null for no limit | |||
*/ | |||
public BigIntegerRangeValidator(String errorMessage, BigInteger minValue, | |||
BigInteger maxValue) { | |||
super(errorMessage, Comparator.naturalOrder(), minValue, maxValue); | |||
} | |||
} |
@@ -0,0 +1,49 @@ | |||
/* | |||
* Copyright 2000-2014 Vaadin Ltd. | |||
* | |||
* Licensed 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 com.vaadin.data.validator; | |||
import java.util.Comparator; | |||
/** | |||
* Validator for validating that an {@link Byte} is inside a given range. | |||
* | |||
* @author Vaadin Ltd. | |||
* @since 8.0 | |||
*/ | |||
@SuppressWarnings("serial") | |||
public class ByteRangeValidator extends RangeValidator<Byte> { | |||
/** | |||
* Creates a validator for checking that an Byte is within a given range. | |||
* | |||
* By default the range is inclusive i.e. both minValue and maxValue are | |||
* valid values. Use {@link #setMinValueIncluded(boolean)} or | |||
* {@link #setMaxValueIncluded(boolean)} to change it. | |||
* | |||
* | |||
* @param errorMessage | |||
* the message to display in case the value does not validate. | |||
* @param minValue | |||
* The minimum value to accept or null for no limit | |||
* @param maxValue | |||
* The maximum value to accept or null for no limit | |||
*/ | |||
public ByteRangeValidator(String errorMessage, Byte minValue, | |||
Byte maxValue) { | |||
super(errorMessage, Comparator.naturalOrder(), minValue, maxValue); | |||
} | |||
} |
@@ -0,0 +1,62 @@ | |||
/* | |||
* Copyright 2000-2014 Vaadin Ltd. | |||
* | |||
* Licensed 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 com.vaadin.data.validator; | |||
import java.util.Comparator; | |||
import java.util.Date; | |||
import com.vaadin.shared.ui.datefield.Resolution; | |||
/** | |||
* Validator for validating that a Date is inside a given range. | |||
* | |||
* <p> | |||
* Note that the comparison is done directly on the Date object so take care | |||
* that the hours/minutes/seconds/milliseconds of the min/max values are | |||
* properly set. | |||
* </p> | |||
* | |||
* @author Vaadin Ltd. | |||
* @since 8.0 | |||
*/ | |||
public class DateRangeValidator extends RangeValidator<Date> { | |||
/** | |||
* Creates a validator for checking that an Date is within a given range. | |||
* <p> | |||
* By default the range is inclusive i.e. both minValue and maxValue are | |||
* valid values. Use {@link #setMinValueIncluded(boolean)} or | |||
* {@link #setMaxValueIncluded(boolean)} to change it. | |||
* </p> | |||
* <p> | |||
* Note that the comparison is done directly on the Date object so take care | |||
* that the hours/minutes/seconds/milliseconds of the min/max values are | |||
* properly set. | |||
* </p> | |||
* | |||
* @param errorMessage | |||
* the message to display in case the value does not validate. | |||
* @param minValue | |||
* The minimum value to accept or null for no limit | |||
* @param maxValue | |||
* The maximum value to accept or null for no limit | |||
*/ | |||
public DateRangeValidator(String errorMessage, Date minValue, Date maxValue, | |||
Resolution resolution) { | |||
super(errorMessage, Comparator.naturalOrder(), minValue, maxValue); | |||
} | |||
} |
@@ -0,0 +1,49 @@ | |||
/* | |||
* Copyright 2000-2014 Vaadin Ltd. | |||
* | |||
* Licensed 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 com.vaadin.data.validator; | |||
import java.util.Comparator; | |||
/** | |||
* Validator for validating that a {@link Double} is inside a given range. | |||
* | |||
* @author Vaadin Ltd. | |||
* @since 8.0 | |||
*/ | |||
@SuppressWarnings("serial") | |||
public class DoubleRangeValidator extends RangeValidator<Double> { | |||
/** | |||
* Creates a validator for checking that an Double is within a given range. | |||
* | |||
* By default the range is inclusive i.e. both minValue and maxValue are | |||
* valid values. Use {@link #setMinValueIncluded(boolean)} or | |||
* {@link #setMaxValueIncluded(boolean)} to change it. | |||
* | |||
* | |||
* @param errorMessage | |||
* the message to display in case the value does not validate. | |||
* @param minValue | |||
* The minimum value to accept or null for no limit | |||
* @param maxValue | |||
* The maximum value to accept or null for no limit | |||
*/ | |||
public DoubleRangeValidator(String errorMessage, Double minValue, | |||
Double maxValue) { | |||
super(errorMessage, Comparator.naturalOrder(), minValue, maxValue); | |||
} | |||
} |
@@ -0,0 +1,44 @@ | |||
/* | |||
* Copyright 2000-2014 Vaadin Ltd. | |||
* | |||
* Licensed 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 com.vaadin.data.validator; | |||
/** | |||
* A string validator for e-mail addresses. The e-mail address syntax is not | |||
* complete according to RFC 822 but handles the vast majority of valid e-mail | |||
* addresses correctly. | |||
* | |||
* @author Vaadin Ltd. | |||
* @since 8.0 | |||
*/ | |||
@SuppressWarnings("serial") | |||
public class EmailValidator extends RegexpValidator { | |||
private static final String PATTERN = "^" + "([a-zA-Z0-9_\\.\\-+])+" // local | |||
+ "@" + "[a-zA-Z0-9-.]+" // domain | |||
+ "\\." + "[a-zA-Z0-9-]{2,}" // tld | |||
+ "$"; | |||
/** | |||
* Creates a validator for checking that a string is a syntactically valid | |||
* e-mail address. | |||
* | |||
* @param errorMessage | |||
* the message to display in case the value does not validate. | |||
*/ | |||
public EmailValidator(String errorMessage) { | |||
super(errorMessage, PATTERN, true); | |||
} | |||
} |
@@ -0,0 +1,49 @@ | |||
/* | |||
* Copyright 2000-2014 Vaadin Ltd. | |||
* | |||
* Licensed 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 com.vaadin.data.validator; | |||
import java.util.Comparator; | |||
/** | |||
* Validator for validating that a {@link Float} is inside a given range. | |||
* | |||
* @author Vaadin Ltd. | |||
* @since 8.0 | |||
*/ | |||
@SuppressWarnings("serial") | |||
public class FloatRangeValidator extends RangeValidator<Float> { | |||
/** | |||
* Creates a validator for checking that an Float is within a given range. | |||
* | |||
* By default the range is inclusive i.e. both minValue and maxValue are | |||
* valid values. Use {@link #setMinValueIncluded(boolean)} or | |||
* {@link #setMaxValueIncluded(boolean)} to change it. | |||
* | |||
* | |||
* @param errorMessage | |||
* the message to display in case the value does not validate. | |||
* @param minValue | |||
* The minimum value to accept or null for no limit | |||
* @param maxValue | |||
* The maximum value to accept or null for no limit | |||
*/ | |||
public FloatRangeValidator(String errorMessage, Float minValue, | |||
Float maxValue) { | |||
super(errorMessage, Comparator.naturalOrder(), minValue, maxValue); | |||
} | |||
} |
@@ -0,0 +1,49 @@ | |||
/* | |||
* Copyright 2000-2014 Vaadin Ltd. | |||
* | |||
* Licensed 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 com.vaadin.data.validator; | |||
import java.util.Comparator; | |||
/** | |||
* Validator for validating that an {@link Integer} is inside a given range. | |||
* | |||
* @author Vaadin Ltd. | |||
* @since 8.0 | |||
*/ | |||
@SuppressWarnings("serial") | |||
public class IntegerRangeValidator extends RangeValidator<Integer> { | |||
/** | |||
* Creates a validator for checking that an Integer is within a given range. | |||
* | |||
* By default the range is inclusive i.e. both minValue and maxValue are | |||
* valid values. Use {@link #setMinValueIncluded(boolean)} or | |||
* {@link #setMaxValueIncluded(boolean)} to change it. | |||
* | |||
* | |||
* @param errorMessage | |||
* the message to display in case the value does not validate. | |||
* @param minValue | |||
* The minimum value to accept or null for no limit | |||
* @param maxValue | |||
* The maximum value to accept or null for no limit | |||
*/ | |||
public IntegerRangeValidator(String errorMessage, Integer minValue, | |||
Integer maxValue) { | |||
super(errorMessage, Comparator.naturalOrder(), minValue, maxValue); | |||
} | |||
} |
@@ -0,0 +1,49 @@ | |||
/* | |||
* Copyright 2000-2014 Vaadin Ltd. | |||
* | |||
* Licensed 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 com.vaadin.data.validator; | |||
import java.util.Comparator; | |||
/** | |||
* Validator for validating that an {@link Long} is inside a given range. | |||
* | |||
* @author Vaadin Ltd. | |||
* @since 8.0 | |||
*/ | |||
@SuppressWarnings("serial") | |||
public class LongRangeValidator extends RangeValidator<Long> { | |||
/** | |||
* Creates a validator for checking that an Long is within a given range. | |||
* | |||
* By default the range is inclusive i.e. both minValue and maxValue are | |||
* valid values. Use {@link #setMinValueIncluded(boolean)} or | |||
* {@link #setMaxValueIncluded(boolean)} to change it. | |||
* | |||
* | |||
* @param errorMessage | |||
* the message to display in case the value does not validate. | |||
* @param minValue | |||
* The minimum value to accept or null for no limit | |||
* @param maxValue | |||
* The maximum value to accept or null for no limit | |||
*/ | |||
public LongRangeValidator(String errorMessage, Long minValue, | |||
Long maxValue) { | |||
super(errorMessage, Comparator.naturalOrder(), minValue, maxValue); | |||
} | |||
} |
@@ -0,0 +1,49 @@ | |||
/* | |||
* Copyright 2000-2014 Vaadin Ltd. | |||
* | |||
* Licensed 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 com.vaadin.data.validator; | |||
import java.util.Objects; | |||
import com.vaadin.data.Result; | |||
/** | |||
* This validator is used for validating properties that do not allow null | |||
* values. | |||
* | |||
* @author Vaadin Ltd. | |||
* @since 8.0 | |||
*/ | |||
@SuppressWarnings("serial") | |||
public class NotNullValidator extends AbstractValidator<String> { | |||
/** | |||
* Creates a new NullValidator. | |||
* | |||
* @param errorMessage | |||
* the error message to display on invalidation. | |||
*/ | |||
public NotNullValidator(String errorMessage) { | |||
super(errorMessage); | |||
} | |||
@Override | |||
public Result<String> apply(String value) { | |||
return Objects.isNull(value) ? Result.error(getMessage(value)) | |||
: Result.ok(value); | |||
} | |||
} |
@@ -0,0 +1,224 @@ | |||
/* | |||
* Copyright 2000-2014 Vaadin Ltd. | |||
* | |||
* Licensed 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 com.vaadin.data.validator; | |||
import java.util.Comparator; | |||
import java.util.Objects; | |||
import com.vaadin.data.Result; | |||
/** | |||
* Verifies that a value is within the given range. | |||
* | |||
* @param <T> | |||
* the type to validate | |||
* @author Vaadin Ltd. | |||
* @since 8.0 | |||
*/ | |||
public class RangeValidator<T> extends AbstractValidator<T> { | |||
private T minValue = null; | |||
private T maxValue = null; | |||
private boolean minValueIncluded = true; | |||
private boolean maxValueIncluded = true; | |||
private 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 <i>natural order</i>. 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. | |||
* <p> | |||
* Null is considered to be less than any non-null value. This means null | |||
* never passes validation if a minimum value is specified. | |||
* | |||
* @param <C> | |||
* 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 <C extends Comparable<? super C>> RangeValidator<C> 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 Result<T> apply(T value) { | |||
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; | |||
} | |||
} |
@@ -0,0 +1,115 @@ | |||
/* | |||
* Copyright 2000-2014 Vaadin Ltd. | |||
* | |||
* Licensed 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 com.vaadin.data.validator; | |||
import java.util.regex.Matcher; | |||
import java.util.regex.Pattern; | |||
import com.vaadin.data.Result; | |||
/** | |||
* A string validator comparing the string against a Java regular expression. | |||
* Both complete matches and substring matches are supported. | |||
* <p> | |||
* For the Java regular expression syntax, see {@link java.util.regex.Pattern}. | |||
* | |||
* @author Vaadin Ltd. | |||
* @since 8.0 | |||
*/ | |||
@SuppressWarnings("serial") | |||
public class RegexpValidator extends AbstractValidator<String> { | |||
private Pattern pattern; | |||
private boolean complete; | |||
private transient Matcher matcher = null; | |||
/** | |||
* Creates a validator for checking that the regular expression matches the | |||
* complete string to validate. | |||
* | |||
* @param errorMessage | |||
* the message to display in case the value does not validate. | |||
* @param regexp | |||
* a Java regular expression | |||
*/ | |||
public RegexpValidator(String errorMessage, String regexp) { | |||
this(errorMessage, regexp, true); | |||
} | |||
/** | |||
* Creates a validator for checking that the regular expression matches the | |||
* string to validate. | |||
* | |||
* @param errorMessage | |||
* the message to display in case the value does not validate. | |||
* @param regexp | |||
* a Java regular expression | |||
* @param complete | |||
* true to use check for a complete match, false to look for a | |||
* matching substring | |||
* | |||
*/ | |||
public RegexpValidator(String errorMessage, String regexp, | |||
boolean complete) { | |||
super(errorMessage); | |||
pattern = Pattern.compile(regexp); | |||
this.complete = complete; | |||
} | |||
@Override | |||
public Result<String> apply(String value) { | |||
return toResult(value, isValid(value)); | |||
} | |||
@Override | |||
public String toString() { | |||
return "RegexpValidator[" + pattern + "]"; | |||
} | |||
/** | |||
* Returns whether the given string matches the regular expression. | |||
* | |||
* @param value | |||
* the string to match | |||
* @return true if the string matched, false otherwise | |||
*/ | |||
protected boolean isValid(String value) { | |||
if (value == null) { | |||
return true; | |||
} | |||
if (complete) { | |||
return getMatcher(value).matches(); | |||
} else { | |||
return getMatcher(value).find(); | |||
} | |||
} | |||
/** | |||
* Returns a new or reused matcher for the pattern. | |||
* | |||
* @param value | |||
* the string to find matches in | |||
* @return a matcher for the string | |||
*/ | |||
private Matcher getMatcher(String value) { | |||
if (matcher == null) { | |||
matcher = pattern.matcher(value); | |||
} else { | |||
matcher.reset(value); | |||
} | |||
return matcher; | |||
} | |||
} |
@@ -0,0 +1,49 @@ | |||
/* | |||
* Copyright 2000-2014 Vaadin Ltd. | |||
* | |||
* Licensed 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 com.vaadin.data.validator; | |||
import java.util.Comparator; | |||
/** | |||
* Validator for validating that an {@link Short} is inside a given range. | |||
* | |||
* @author Vaadin Ltd. | |||
* @since 8.0 | |||
*/ | |||
@SuppressWarnings("serial") | |||
public class ShortRangeValidator extends RangeValidator<Short> { | |||
/** | |||
* Creates a validator for checking that an Short is within a given range. | |||
* | |||
* By default the range is inclusive i.e. both minValue and maxValue are | |||
* valid values. Use {@link #setMinValueIncluded(boolean)} or | |||
* {@link #setMaxValueIncluded(boolean)} to change it. | |||
* | |||
* | |||
* @param errorMessage | |||
* the message to display in case the value does not validate. | |||
* @param minValue | |||
* The minimum value to accept or null for no limit | |||
* @param maxValue | |||
* The maximum value to accept or null for no limit | |||
*/ | |||
public ShortRangeValidator(String errorMessage, Short minValue, | |||
Short maxValue) { | |||
super(errorMessage, Comparator.naturalOrder(), minValue, maxValue); | |||
} | |||
} |
@@ -0,0 +1,104 @@ | |||
/* | |||
* Copyright 2000-2014 Vaadin Ltd. | |||
* | |||
* Licensed 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 com.vaadin.data.validator; | |||
import com.vaadin.data.Result; | |||
/** | |||
* Verifies that the length of a string is within the given range. | |||
* | |||
* @author Vaadin Ltd. | |||
* @since 8.0 | |||
*/ | |||
@SuppressWarnings("serial") | |||
public class StringLengthValidator extends AbstractValidator<String> { | |||
private RangeValidator<Integer> validator; | |||
/** | |||
* Creates a new StringLengthValidator with a given error message and | |||
* minimum and maximum length limits. | |||
* | |||
* @param errorMessage | |||
* the error message to return if validation fails | |||
* @param minLength | |||
* the minimum permissible length of the string or null for no | |||
* limit. | |||
* @param maxLength | |||
* the maximum permissible length of the string or null for no | |||
* limit. | |||
*/ | |||
public StringLengthValidator(String errorMessage, Integer minLength, | |||
Integer maxLength) { | |||
super(errorMessage); | |||
validator = RangeValidator.of(errorMessage, minLength, maxLength); | |||
} | |||
@Override | |||
public Result<String> apply(String value) { | |||
if (value == null) { | |||
return toResult(value, true); | |||
} | |||
Result<?> lengthCheck = validator.apply(value.length()); | |||
return toResult(value, !lengthCheck.isError()); | |||
} | |||
/** | |||
* Gets the maximum permissible length of the string. | |||
* | |||
* @return the maximum length of the string or null if there is no limit | |||
*/ | |||
public Integer getMaxLength() { | |||
return validator.getMaxValue(); | |||
} | |||
/** | |||
* Gets the minimum permissible length of the string. | |||
* | |||
* @return the minimum length of the string or null if there is no limit | |||
*/ | |||
public Integer getMinLength() { | |||
return validator.getMinValue(); | |||
} | |||
/** | |||
* Sets the maximum permissible length of the string. | |||
* | |||
* @param maxLength | |||
* the maximum length to accept or null for no limit | |||
*/ | |||
public void setMaxLength(Integer maxLength) { | |||
validator.setMaxValue(maxLength); | |||
} | |||
/** | |||
* Sets the minimum permissible length. | |||
* | |||
* @param minLength | |||
* the minimum length to accept or null for no limit | |||
*/ | |||
public void setMinLength(Integer minLength) { | |||
validator.setMaxValue(minLength); | |||
} | |||
@Override | |||
public String toString() { | |||
return String.format("%s[%d, %d]", getClass().getSimpleName(), | |||
getMinLength(), getMaxLength()); | |||
} | |||
} |
@@ -0,0 +1,82 @@ | |||
package com.vaadin.data.validator; | |||
import java.util.Calendar; | |||
import java.util.Locale; | |||
import org.junit.Test; | |||
import com.vaadin.tests.data.bean.Address; | |||
import com.vaadin.tests.data.bean.BeanToValidate; | |||
public class BeanValidatorTest extends ValidatorTestBase { | |||
@Test | |||
public void testFirstNameNullFails() { | |||
assertFails(null, "may not be null", validator("firstname")); | |||
} | |||
@Test | |||
public void testFirstNameTooShortFails() { | |||
assertFails("x", "size must be between 3 and 16", | |||
validator("firstname")); | |||
} | |||
@Test | |||
public void testFirstNameLongEnoughPasses() { | |||
assertPasses("Magi", validator("firstname")); | |||
} | |||
@Test | |||
public void testAgeTooYoungFails() { | |||
assertFails(14, "Must be 18 or above", validator("age")); | |||
} | |||
@Test | |||
public void testDateOfBirthNullPasses() { | |||
assertPasses(null, validator("dateOfBirth")); | |||
} | |||
@Test | |||
public void testDateOfBirthInTheFutureFails() { | |||
Calendar year3k = Calendar.getInstance(); | |||
year3k.set(3000, 0, 1); | |||
assertFails(year3k, "must be in the past", validator("dateOfBirth")); | |||
} | |||
@Test | |||
public void testAddressesEmptyArrayPasses() { | |||
Address[] noAddresses = {}; | |||
assertPasses(noAddresses, validator("addresses")); | |||
} | |||
@Test | |||
public void testAddressesNullFails() { | |||
assertFails(null, "may not be null", validator("addresses")); | |||
} | |||
@Test | |||
public void testInvalidDecimalsFailsInFrench() { | |||
BeanValidator v = validator("decimals", Locale.FRENCH); | |||
assertFails("1234.567", "Valeur numérique hors limite " | |||
+ "(<3 chiffres>.<2 chiffres> attendus)", v); | |||
} | |||
@Test | |||
public void testAddressNestedPropertyInvalidPostalCodeFails() { | |||
assertFails(100_000, "must be less than or equal to 99999", | |||
validator("address.postalCode")); | |||
} | |||
@Test | |||
public void testNullValuePasses() { | |||
assertPasses(null, validator("nickname")); | |||
} | |||
private BeanValidator validator(String propertyName) { | |||
return new BeanValidator(BeanToValidate.class, propertyName); | |||
} | |||
private BeanValidator validator(String propertyName, Locale locale) { | |||
return new BeanValidator(BeanToValidate.class, propertyName, locale); | |||
} | |||
} |
@@ -0,0 +1,142 @@ | |||
/* | |||
* Copyright 2000-2016 Vaadin Ltd. | |||
* | |||
* Licensed 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 com.vaadin.data.validator; | |||
import java.util.List; | |||
import org.junit.Assert; | |||
import org.junit.Before; | |||
import org.junit.Test; | |||
import com.vaadin.data.Binder; | |||
import com.vaadin.data.ValidationError; | |||
import com.vaadin.server.AbstractErrorMessage; | |||
import com.vaadin.tests.data.bean.Person; | |||
import com.vaadin.ui.AbstractField; | |||
/** | |||
* Book of Vaadin tests. | |||
* | |||
* @author Vaadin Ltd | |||
* | |||
*/ | |||
public class BoVTest { | |||
static class TextField extends AbstractField<String> { | |||
String value = ""; | |||
@Override | |||
public String getValue() { | |||
return value; | |||
} | |||
@Override | |||
protected void doSetValue(String value) { | |||
this.value = value; | |||
} | |||
} | |||
private Binder<Person> binder; | |||
private TextField field; | |||
private Person person = new Person(); | |||
@Before | |||
public void setUp() { | |||
binder = new Binder<>(); | |||
field = new TextField(); | |||
} | |||
@Test | |||
public void simpleEmailValidator() { | |||
binder.forField(field) | |||
// Explicit validator instance | |||
.withValidator(new EmailValidator( | |||
"This doesn't look like a valid email address")) | |||
.bind(Person::getEmail, Person::setEmail); | |||
field.setValue("not-email"); | |||
List<ValidationError<?>> errors = binder.validate(); | |||
Assert.assertEquals(1, errors.size()); | |||
Assert.assertEquals("This doesn't look like a valid email address", | |||
errors.get(0).getMessage()); | |||
Assert.assertEquals("This doesn't look like a valid email address", | |||
((AbstractErrorMessage) field.getErrorMessage()).getMessage()); | |||
field.setValue("abc@vaadin.com"); | |||
errors = binder.validate(); | |||
Assert.assertEquals(0, errors.size()); | |||
Assert.assertNull(field.getErrorMessage()); | |||
} | |||
@Test | |||
public void nameLengthTest() { | |||
binder.forField(field) | |||
// Validator defined based on a lambda and an error message | |||
.withValidator(name -> name.length() >= 3, | |||
"Last name must contain at least three characters") | |||
.bind(Person::getLastName, Person::setLastName); | |||
field.setValue("a"); | |||
List<ValidationError<?>> errors = binder.validate(); | |||
Assert.assertEquals(1, errors.size()); | |||
Assert.assertEquals("Last name must contain at least three characters", | |||
errors.get(0).getMessage()); | |||
Assert.assertEquals("Last name must contain at least three characters", | |||
((AbstractErrorMessage) field.getErrorMessage()).getMessage()); | |||
field.setValue("long last name"); | |||
errors = binder.validate(); | |||
Assert.assertEquals(0, errors.size()); | |||
Assert.assertNull(field.getErrorMessage()); | |||
} | |||
@Test | |||
public void chainedEmailValidator() { | |||
binder.forField(field) | |||
// Explicit validator instance | |||
.withValidator(new EmailValidator( | |||
"This doesn't look like a valid email address")) | |||
.withValidator(email -> email.endsWith("@acme.com"), | |||
"Only acme.com email addresses are allowed") | |||
.bind(Person::getEmail, Person::setEmail); | |||
field.setValue("not-email"); | |||
List<ValidationError<?>> errors = binder.validate(); | |||
Assert.assertEquals(2, errors.size()); | |||
Assert.assertEquals("This doesn't look like a valid email address", | |||
errors.get(0).getMessage()); | |||
Assert.assertEquals("Only acme.com email addresses are allowed", | |||
errors.get(1).getMessage()); | |||
Assert.assertEquals("This doesn't look like a valid email address", | |||
((AbstractErrorMessage) field.getErrorMessage()).getMessage()); | |||
field.setValue("abc@vaadin.com"); | |||
errors = binder.validate(); | |||
Assert.assertEquals(1, errors.size()); | |||
Assert.assertEquals("Only acme.com email addresses are allowed", | |||
errors.get(0).getMessage()); | |||
Assert.assertEquals("Only acme.com email addresses are allowed", | |||
((AbstractErrorMessage) field.getErrorMessage()).getMessage()); | |||
field.setValue("abc@acme.com"); | |||
errors = binder.validate(); | |||
Assert.assertEquals(0, errors.size()); | |||
Assert.assertNull(field.getErrorMessage()); | |||
} | |||
} |
@@ -0,0 +1,98 @@ | |||
package com.vaadin.data.validator; | |||
import org.junit.Test; | |||
public class EmailValidatorTest extends ValidatorTestBase { | |||
@Test | |||
public void testNullStringFails() { | |||
assertPasses(null, shouldNotFail()); | |||
} | |||
@Test | |||
public void testEmptyStringFails() { | |||
assertFails("", validator("empty string not allowed")); | |||
} | |||
@Test | |||
public void testStringWithoutAtSignFails() { | |||
assertFails("johannesd.vaadin", validator("@ is required")); | |||
} | |||
@Test | |||
public void testMissingLocalPartFails() { | |||
RegexpValidator v = validator("local part is required"); | |||
assertFails("@localhost", v); | |||
assertFails(" @localhost", v); | |||
} | |||
@Test | |||
public void testNonAsciiEmailFails() { | |||
RegexpValidator v = validator("accented letters not allowed"); | |||
assertFails("jöhännes@vaadin.com", v); | |||
assertFails("johannes@váádìn.com", v); | |||
assertFails("johannes@vaadin.cõm", v); | |||
} | |||
@Test | |||
public void testLocalPartWithPunctuationPasses() { | |||
RegexpValidator v = shouldNotFail(); | |||
assertPasses("johannesd+test@vaadin.com", v); | |||
assertPasses("johannes.dahlstrom@vaadin.com", v); | |||
assertPasses("johannes_d@vaadin.com", v); | |||
} | |||
@Test | |||
public void testEmailWithoutDomainPartFails() { | |||
assertFails("johannesd@", validator("domain part is required")); | |||
} | |||
@Test | |||
public void testComplexDomainPasses() { | |||
assertPasses("johannesd@foo.bar.baz.vaadin.com", shouldNotFail()); | |||
} | |||
@Test | |||
public void testDomainWithPunctuationPasses() { | |||
assertPasses("johannesd@vaadin-dev.com", shouldNotFail()); | |||
} | |||
@Test | |||
public void testMissingTldFails() { | |||
assertFails("johannesd@localhost", validator("tld is required")); | |||
} | |||
@Test | |||
public void testOneLetterTldFails() { | |||
assertFails("johannesd@vaadin.f", | |||
validator("one-letter tld not allowed")); | |||
} | |||
@Test | |||
public void testLongTldPasses() { | |||
assertPasses("joonas@vaadin.management", shouldNotFail()); | |||
} | |||
@Test | |||
public void testIdnTldPasses() { | |||
assertPasses("leif@vaadin.XN--VERMGENSBERATER-CTB", shouldNotFail()); | |||
} | |||
@Test | |||
public void testYelledEmailPasses() { | |||
assertPasses("JOHANNESD@VAADIN.COM", shouldNotFail()); | |||
} | |||
@Test | |||
public void testEmailWithDigitsPasses() { | |||
assertPasses("johannes84@v44d1n.com", shouldNotFail()); | |||
} | |||
private EmailValidator validator(String errorMessage) { | |||
return new EmailValidator(errorMessage); | |||
} | |||
private EmailValidator shouldNotFail() { | |||
return validator("this should not fail"); | |||
} | |||
} |
@@ -0,0 +1,42 @@ | |||
/* | |||
* Copyright 2000-2016 Vaadin Ltd. | |||
* | |||
* Licensed 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 com.vaadin.data.validator; | |||
import org.junit.Assert; | |||
import org.junit.Test; | |||
import com.vaadin.data.Result; | |||
public class NullValidatorTest { | |||
@Test | |||
public void nullValueIsDisallowed() { | |||
NotNullValidator validator = new NotNullValidator("foo"); | |||
Result<String> result = validator.apply(null); | |||
Assert.assertTrue(result.isError()); | |||
Assert.assertEquals("foo", result.getMessage().get()); | |||
} | |||
@Test | |||
public void nonNullValueIsAllowed() { | |||
NotNullValidator validator = new NotNullValidator("foo"); | |||
Result<String> result = validator.apply("bar"); | |||
Assert.assertFalse(result.isError()); | |||
result.ifOk(value -> Assert.assertEquals("bar", value)); | |||
result.ifError(msg -> Assert.fail()); | |||
} | |||
} |
@@ -0,0 +1,105 @@ | |||
package com.vaadin.data.validator; | |||
import java.time.LocalDate; | |||
import org.junit.Test; | |||
public class RangeValidatorTest extends ValidatorTestBase { | |||
@Test | |||
public void testIntegerRangeValidIntPasses() { | |||
assertPasses(10, | |||
RangeValidator.of("Must be between -123 and 42", -123, 42)); | |||
} | |||
@Test | |||
public void testIntegerRangeInvalidIntFails() { | |||
assertFails(123, | |||
RangeValidator.of("Must be between -123 and 42", -123, 42)); | |||
} | |||
@Test | |||
public void testRangeWithoutUpperBoundLargeIntegerPasses() { | |||
assertPasses(Integer.MAX_VALUE, | |||
RangeValidator.of("Must be at least 18", 18, null)); | |||
} | |||
@Test | |||
public void testRangeWithoutUpperBoundSmallIntegerFails() { | |||
assertFails(17, RangeValidator.of("Must be at least 18", 18, null)); | |||
} | |||
@Test | |||
public void testRangeWithoutLowerBoundSmallIntegerPasses() { | |||
assertPasses(Integer.MIN_VALUE, | |||
RangeValidator.of("Must be at most 0", null, 0)); | |||
} | |||
@Test | |||
public void testRangeWithoutLowerBoundLargeIntegerFails() { | |||
assertFails(1, RangeValidator.of("Must be at most 0", null, 0)); | |||
} | |||
@Test | |||
public void testUnboundedRangePassesEverything() { | |||
RangeValidator<Integer> v = RangeValidator.of("This should not happen!", | |||
null, null); | |||
assertPasses(Integer.MIN_VALUE, v); | |||
assertPasses(0, v); | |||
assertPasses(null, v); | |||
assertPasses(Integer.MAX_VALUE, v); | |||
} | |||
@Test | |||
public void testBoundsInclusiveByDefault() { | |||
RangeValidator<Integer> v = RangeValidator | |||
.of("Must be between -10 and 10", -10, 10); | |||
assertPasses(-10, v); | |||
assertPasses(10, v); | |||
} | |||
@Test | |||
public void testUpperBoundExclusive() { | |||
RangeValidator<Integer> v = RangeValidator | |||
.of("Must be between -10 and 10", -10, 10); | |||
v.setMaxValueIncluded(false); | |||
assertPasses(-10, v); | |||
assertPasses(9, v); | |||
assertFails(10, v); | |||
} | |||
@Test | |||
public void testLowerBoundExclusive() { | |||
RangeValidator<Integer> v = RangeValidator | |||
.of("Must be between -10 and 10", -10, 10); | |||
v.setMinValueIncluded(false); | |||
assertFails(-10, v); | |||
assertPasses(-9, v); | |||
assertPasses(10, v); | |||
} | |||
@Test | |||
public void testNullLessThanEverything() { | |||
RangeValidator<Integer> v = RangeValidator.of("Must be any integer", | |||
Integer.MIN_VALUE, Integer.MAX_VALUE); | |||
assertPasses(null, v); | |||
v = RangeValidator.of("Must be very small", null, Integer.MIN_VALUE); | |||
assertPasses(null, v); | |||
} | |||
@Test | |||
public void testDateRange() { | |||
RangeValidator<LocalDate> v = RangeValidator.of("Date must be in 2016", | |||
LocalDate.of(2016, 1, 1), LocalDate.of(2016, 12, 31)); | |||
assertFails(LocalDate.ofEpochDay(0), v); | |||
assertPasses(LocalDate.of(2016, 7, 31), v); | |||
assertFails(LocalDate.ofEpochDay(1_000_000_000), v); | |||
} | |||
} |
@@ -0,0 +1,71 @@ | |||
package com.vaadin.data.validator; | |||
import org.junit.Test; | |||
public class RegexpValidatorTest extends ValidatorTestBase { | |||
@Test | |||
public void testNullStringFails() { | |||
assertPasses(null, new RegexpValidator("Should be 'abc'", "abc")); | |||
} | |||
@Test | |||
public void testEmptyPatternMatchesEmptyString() { | |||
assertPasses("", new RegexpValidator("Should be empty", "", true)); | |||
} | |||
@Test | |||
public void testEmptyPatternDoesNotMatchNonEmptyString() { | |||
assertFails("x", new RegexpValidator("Should be empty", "", true)); | |||
} | |||
@Test | |||
public void testPatternMatchesString() { | |||
RegexpValidator v = new RegexpValidator( | |||
"Should be foo and bar repeating", "(foo|bar)+", true); | |||
assertPasses("foo", v); | |||
assertPasses("barfoo", v); | |||
assertPasses("foobarbarbarfoobarfoofoobarbarfoofoofoobar", v); | |||
} | |||
@Test | |||
public void testPatternDoesNotMatchString() { | |||
RegexpValidator v = new RegexpValidator( | |||
"Should be foo and bar repeating", "(foo|bar)+", true); | |||
assertFails("", v); | |||
assertFails("barf", v); | |||
assertFails(" bar", v); | |||
assertFails("foobarbarbarfoobar.foofoobarbarfoofoofoobar", v); | |||
} | |||
@Test | |||
public void testEmptyPatternFoundInAnyString() { | |||
RegexpValidator v = new RegexpValidator("Should always pass", "", | |||
false); | |||
assertPasses("", v); | |||
assertPasses(" ", v); | |||
assertPasses("qwertyuiopasdfghjklzxcvbnm", v); | |||
} | |||
@Test | |||
public void testPatternFoundInString() { | |||
RegexpValidator v = new RegexpValidator("Should contain a number", | |||
"\\d+", false); | |||
assertPasses("0", v); | |||
assertPasses(" 123 ", v); | |||
assertPasses("qwerty9iop", v); | |||
} | |||
@Test | |||
public void testPatternNotFoundInString() { | |||
RegexpValidator v = new RegexpValidator("Should contain a number", | |||
"\\d+", false); | |||
assertFails("", v); | |||
assertFails("qwertyiop", v); | |||
} | |||
} |
@@ -0,0 +1,41 @@ | |||
package com.vaadin.data.validator; | |||
import java.util.stream.Collectors; | |||
import java.util.stream.Stream; | |||
import org.junit.Test; | |||
public class StringLengthValidatorTest extends ValidatorTestBase { | |||
private static String LONG_STRING = Stream.generate(() -> "x").limit(1000) | |||
.collect(Collectors.joining()); | |||
@Test | |||
public void testNullStringFails() { | |||
assertPasses(null, new StringLengthValidator("", 0, 10)); | |||
} | |||
@Test | |||
public void testMaxLengthTooLongStringFails() { | |||
assertFails(LONG_STRING, | |||
new StringLengthValidator("Should be at most 10", null, 10)); | |||
} | |||
@Test | |||
public void testMaxLengthStringPasses() { | |||
assertPasses(LONG_STRING, new StringLengthValidator( | |||
"Should be at most 1000", null, 1000)); | |||
} | |||
@Test | |||
public void testMinLengthEmptyStringFails() { | |||
assertFails("", | |||
new StringLengthValidator("Should be at least 1", 1, null)); | |||
} | |||
@Test | |||
public void testMinLengthStringPasses() { | |||
assertPasses("å", | |||
new StringLengthValidator("Should be at least 1", 1, null)); | |||
} | |||
} |
@@ -0,0 +1,24 @@ | |||
package com.vaadin.data.validator; | |||
import org.junit.Assert; | |||
import com.vaadin.data.Validator; | |||
public class ValidatorTestBase { | |||
protected <T> void assertPasses(T value, Validator<? super T> v) { | |||
v.apply(value).handle(val -> Assert.assertEquals(value, val), | |||
err -> Assert | |||
.fail(value + " should pass " + v + " but got " + err)); | |||
} | |||
protected <T> void assertFails(T value, String errorMessage, | |||
Validator<? super T> v) { | |||
v.apply(value).handle(val -> Assert.fail(value + " should fail " + v), | |||
err -> Assert.assertEquals(errorMessage, err)); | |||
} | |||
protected <T> void assertFails(T value, AbstractValidator<? super T> v) { | |||
assertFails(value, v.getMessage(value), v); | |||
} | |||
} |
@@ -2,13 +2,26 @@ package com.vaadin.tests.data.bean; | |||
import java.io.Serializable; | |||
import javax.validation.constraints.Max; | |||
import javax.validation.constraints.Min; | |||
import javax.validation.constraints.NotNull; | |||
@SuppressWarnings("serial") | |||
public class Address implements Serializable { | |||
@NotNull | |||
private String streetAddress = ""; | |||
private Integer postalCode = null; | |||
@NotNull | |||
@Min(0) | |||
@Max(99999) | |||
private Integer postalCode = 0; | |||
@NotNull | |||
private String city = ""; | |||
private Country country = null; | |||
@NotNull | |||
private Country country = Country.FINLAND; | |||
public Address() { | |||
@@ -1,13 +1,18 @@ | |||
package com.vaadin.tests.data.bean; | |||
import java.util.Calendar; | |||
import javax.validation.Valid; | |||
import javax.validation.constraints.Digits; | |||
import javax.validation.constraints.Max; | |||
import javax.validation.constraints.Min; | |||
import javax.validation.constraints.NotNull; | |||
import javax.validation.constraints.Past; | |||
import javax.validation.constraints.Pattern; | |||
import javax.validation.constraints.Size; | |||
public class BeanToValidate { | |||
@NotNull | |||
@Size(min = 3, max = 16) | |||
private String firstname; | |||
@@ -26,6 +31,17 @@ public class BeanToValidate { | |||
@Size(min = 3, max = 6, message = "Must contain 3 - 6 letters") | |||
private String nickname; | |||
@Past | |||
private Calendar dateOfBirth; | |||
@NotNull | |||
@Valid | |||
private Address[] addresses; | |||
@NotNull | |||
@Valid | |||
private Address address; | |||
public String getFirstname() { | |||
return firstname; | |||
} | |||
@@ -66,4 +82,27 @@ public class BeanToValidate { | |||
this.nickname = nickname; | |||
} | |||
public Calendar getDateOfBirth() { | |||
return dateOfBirth; | |||
} | |||
public void setDateOfBirth(Calendar dateOfBirth) { | |||
this.dateOfBirth = dateOfBirth; | |||
} | |||
public Address[] getAddresses() { | |||
return addresses; | |||
} | |||
public void setAddresses(Address[] address) { | |||
this.addresses = address; | |||
} | |||
public Address getAddress() { | |||
return address; | |||
} | |||
public void setAddress(Address address) { | |||
this.address = address; | |||
} | |||
} |
@@ -27,8 +27,7 @@ public class ClassesSerializableTest { | |||
private static String[] BASE_PACKAGES = { "com.vaadin" }; | |||
private static String[] EXCLUDED_PATTERNS = { | |||
"com\\.vaadin\\.demo\\..*", // | |||
private static String[] EXCLUDED_PATTERNS = { "com\\.vaadin\\.demo\\..*", // | |||
"com\\.vaadin\\.external\\.org\\.apache\\.commons\\.fileupload\\..*", // | |||
"com\\.vaadin\\.launcher\\..*", // | |||
"com\\.vaadin\\.client\\..*", // | |||
@@ -65,6 +64,8 @@ public class ClassesSerializableTest { | |||
"com\\.vaadin\\.data\\.util\\.sqlcontainer\\.connection\\.MockInitialContextFactory", | |||
"com\\.vaadin\\.data\\.util\\.sqlcontainer\\.DataGenerator", | |||
"com\\.vaadin\\.data\\.util\\.sqlcontainer\\.FreeformQueryUtil", | |||
// the JSR-303 constraint interpolation context | |||
"com\\.vaadin\\.data\\.validator\\.BeanValidator\\$1", // | |||
"com\\.vaadin\\.sass.*", // | |||
"com\\.vaadin\\.testbench.*", // | |||
"com\\.vaadin\\.util\\.CurrentInstance\\$1", // | |||
@@ -149,8 +150,9 @@ public class ClassesSerializableTest { | |||
nonSerializableString += ")"; | |||
} | |||
} | |||
Assert.fail("Serializable not implemented by the following classes and interfaces: " | |||
+ nonSerializableString); | |||
Assert.fail( | |||
"Serializable not implemented by the following classes and interfaces: " | |||
+ nonSerializableString); | |||
} | |||
} | |||
@@ -272,8 +274,8 @@ public class ClassesSerializableTest { | |||
while (e.hasMoreElements()) { | |||
JarEntry entry = e.nextElement(); | |||
if (entry.getName().endsWith(".class")) { | |||
String nameWithoutExtension = entry.getName().replaceAll( | |||
"\\.class", ""); | |||
String nameWithoutExtension = entry.getName() | |||
.replaceAll("\\.class", ""); | |||
String className = nameWithoutExtension.replace('/', '.'); | |||
classes.add(className); | |||
} |
@@ -12,56 +12,58 @@ import com.vaadin.tests.data.bean.BeanToValidate; | |||
public class BeanValidationTest { | |||
@Test(expected = InvalidValueException.class) | |||
public void testBeanValidationNull() { | |||
LegacyBeanValidator validator = new LegacyBeanValidator(BeanToValidate.class, | |||
"firstname"); | |||
LegacyBeanValidator validator = new LegacyBeanValidator( | |||
BeanToValidate.class, "firstname"); | |||
validator.validate(null); | |||
} | |||
@Test(expected = InvalidValueException.class) | |||
public void testBeanValidationStringTooShort() { | |||
LegacyBeanValidator validator = new LegacyBeanValidator(BeanToValidate.class, | |||
"firstname"); | |||
LegacyBeanValidator validator = new LegacyBeanValidator( | |||
BeanToValidate.class, "firstname"); | |||
validator.validate("aa"); | |||
} | |||
@Test | |||
public void testBeanValidationStringOk() { | |||
LegacyBeanValidator validator = new LegacyBeanValidator(BeanToValidate.class, | |||
"firstname"); | |||
LegacyBeanValidator validator = new LegacyBeanValidator( | |||
BeanToValidate.class, "firstname"); | |||
validator.validate("aaa"); | |||
} | |||
@Test(expected = InvalidValueException.class) | |||
public void testBeanValidationIntegerTooSmall() { | |||
LegacyBeanValidator validator = new LegacyBeanValidator(BeanToValidate.class, "age"); | |||
LegacyBeanValidator validator = new LegacyBeanValidator( | |||
BeanToValidate.class, "age"); | |||
validator.validate(17); | |||
} | |||
@Test | |||
public void testBeanValidationIntegerOk() { | |||
LegacyBeanValidator validator = new LegacyBeanValidator(BeanToValidate.class, "age"); | |||
LegacyBeanValidator validator = new LegacyBeanValidator( | |||
BeanToValidate.class, "age"); | |||
validator.validate(18); | |||
} | |||
@Test(expected = InvalidValueException.class) | |||
public void testBeanValidationTooManyDigits() { | |||
LegacyBeanValidator validator = new LegacyBeanValidator(BeanToValidate.class, | |||
"decimals"); | |||
LegacyBeanValidator validator = new LegacyBeanValidator( | |||
BeanToValidate.class, "decimals"); | |||
validator.validate("1234.567"); | |||
} | |||
@Test | |||
public void testBeanValidationDigitsOk() { | |||
LegacyBeanValidator validator = new LegacyBeanValidator(BeanToValidate.class, | |||
"decimals"); | |||
LegacyBeanValidator validator = new LegacyBeanValidator( | |||
BeanToValidate.class, "decimals"); | |||
validator.validate("123.45"); | |||
} | |||
@Test | |||
public void testBeanValidationException_OneValidationError() { | |||
InvalidValueException[] causes = null; | |||
LegacyBeanValidator validator = new LegacyBeanValidator(BeanToValidate.class, | |||
"lastname"); | |||
LegacyBeanValidator validator = new LegacyBeanValidator( | |||
BeanToValidate.class, "lastname"); | |||
try { | |||
validator.validate(null); | |||
} catch (InvalidValueException e) { | |||
@@ -74,8 +76,8 @@ public class BeanValidationTest { | |||
@Test | |||
public void testBeanValidationsException_TwoValidationErrors() { | |||
InvalidValueException[] causes = null; | |||
LegacyBeanValidator validator = new LegacyBeanValidator(BeanToValidate.class, | |||
"nickname"); | |||
LegacyBeanValidator validator = new LegacyBeanValidator( | |||
BeanToValidate.class, "nickname"); | |||
try { | |||
validator.validate("A"); | |||
} catch (InvalidValueException e) { |
@@ -27,7 +27,8 @@ public class AbstractFieldCommitWithInvalidValues extends TestBase { | |||
protected void setup() { | |||
tf = new TextField("A field, must contain 1-2 chars", | |||
new ObjectProperty<String>("a")); | |||
tf.addValidator(new LegacyStringLengthValidator("Invalid length", 1, 2, false)); | |||
tf.addValidator( | |||
new LegacyStringLengthValidator("Invalid length", 1, 2, false)); | |||
tf.setBuffered(true); | |||
tf.setRequired(true); | |||
@@ -86,34 +86,34 @@ public class DateFieldRangeValidation extends TestBase { | |||
actualDateField = createDateField(); | |||
actualDateField.setValue(new Date(2011 - 1900, 12 - 1, 1)); | |||
actualDateField.addValidator(new LegacyRangeValidator<Date>("", Date.class, | |||
null, null) { | |||
@Override | |||
public boolean isMinValueIncluded() { | |||
return range.isFromInclusive(); | |||
} | |||
@Override | |||
public boolean isMaxValueIncluded() { | |||
return range.isToInclusive(); | |||
} | |||
@Override | |||
public Date getMaxValue() { | |||
return range.getTo(); | |||
} | |||
@Override | |||
public Date getMinValue() { | |||
return range.getFrom(); | |||
} | |||
@Override | |||
public String getErrorMessage() { | |||
return "Date must be in range " + getMinValue() + " - " | |||
+ getMaxValue(); | |||
} | |||
}); | |||
actualDateField.addValidator( | |||
new LegacyRangeValidator<Date>("", Date.class, null, null) { | |||
@Override | |||
public boolean isMinValueIncluded() { | |||
return range.isFromInclusive(); | |||
} | |||
@Override | |||
public boolean isMaxValueIncluded() { | |||
return range.isToInclusive(); | |||
} | |||
@Override | |||
public Date getMaxValue() { | |||
return range.getTo(); | |||
} | |||
@Override | |||
public Date getMinValue() { | |||
return range.getFrom(); | |||
} | |||
@Override | |||
public String getErrorMessage() { | |||
return "Date must be in range " + getMinValue() + " - " | |||
+ getMaxValue(); | |||
} | |||
}); | |||
addComponent(fromField); | |||
addComponent(fromInclusive); | |||
addComponent(toField); |
@@ -25,10 +25,11 @@ public class DefaultHandleUnparsableDateField extends TestBase { | |||
} | |||
}); | |||
final DateField validated = new DateField("Validated Default DateField"); | |||
final DateField validated = new DateField( | |||
"Validated Default DateField"); | |||
validated.setImmediate(true); | |||
validated.addValidator(new LegacyNullValidator("Validator: Date is NULL", | |||
false)); | |||
validated.addValidator( | |||
new LegacyNullValidator("Validator: Date is NULL", false)); | |||
addComponent(validated); | |||
} | |||
@@ -28,7 +28,8 @@ public class FormCommitWithInvalidValues extends TestBase { | |||
form = new Form(); | |||
form.setFooter(null); | |||
TextField tf = new TextField("A field, must contain 1-2 chars"); | |||
tf.addValidator(new LegacyStringLengthValidator("Invalid length", 1, 2, false)); | |||
tf.addValidator( | |||
new LegacyStringLengthValidator("Invalid length", 1, 2, false)); | |||
tf.setRequired(true); | |||
form.addField("a", tf); |
@@ -96,11 +96,10 @@ public class GridThemeUI extends AbstractTestUIWithLog { | |||
getColumn("lastName").setEditable(false); | |||
setSizeFull(); | |||
getColumn("age").getEditorField().addValidator( | |||
new LegacyIntegerRangeValidator("Must be between 0 and 100", 0, | |||
100)); | |||
getColumn("birthDate").setRenderer( | |||
new DateRenderer(DateFormat.getDateInstance( | |||
DateFormat.MEDIUM, Locale.US))); | |||
new LegacyIntegerRangeValidator("Must be between 0 and 100", | |||
0, 100)); | |||
getColumn("birthDate").setRenderer(new DateRenderer( | |||
DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.US))); | |||
} | |||
} | |||
@@ -137,11 +136,10 @@ public class GridThemeUI extends AbstractTestUIWithLog { | |||
setEditorEnabled(true); | |||
setSizeFull(); | |||
getColumn("age").getEditorField().addValidator( | |||
new LegacyIntegerRangeValidator("Must be between 0 and 100", 0, | |||
100)); | |||
getColumn("birthDate").setRenderer( | |||
new DateRenderer(DateFormat.getDateInstance( | |||
DateFormat.MEDIUM, Locale.US))); | |||
new LegacyIntegerRangeValidator("Must be between 0 and 100", | |||
0, 100)); | |||
getColumn("birthDate").setRenderer(new DateRenderer( | |||
DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.US))); | |||
addFooterRowAt(0); | |||
} |
@@ -199,7 +199,8 @@ public abstract class AbstractBasicCrud extends AbstractTestUIWithLog { | |||
protected BeanFieldGroup<ComplexPerson> fieldGroup = new BeanFieldGroup<ComplexPerson>( | |||
ComplexPerson.class) { | |||
@Override | |||
protected void configureField(com.vaadin.legacy.ui.LegacyField<?> field) { | |||
protected void configureField( | |||
com.vaadin.legacy.ui.LegacyField<?> field) { | |||
super.configureField(field); | |||
if (field.getCaption().equals("Postal code")) { | |||
// Last name editing is disabled through property. | |||
@@ -264,8 +265,8 @@ public abstract class AbstractBasicCrud extends AbstractTestUIWithLog { | |||
public AutoGeneratedForm(Class<? extends LegacyField> class1) { | |||
for (String p : columns) { | |||
LegacyField f = fieldGroup.getFieldFactory().createField( | |||
container.getType(p), class1); | |||
LegacyField f = fieldGroup.getFieldFactory() | |||
.createField(container.getType(p), class1); | |||
f.setCaption(SharedUtil.propertyIdToHumanFriendly(p)); | |||
fieldGroup.bind(f, p); | |||
addComponent(f); |
@@ -44,21 +44,18 @@ public class BasicCrudGridEditorRow extends AbstractBasicCrud { | |||
grid.addSelectionListener(new SelectionListener() { | |||
@Override | |||
public void select(SelectionEvent event) { | |||
Item item = grid.getContainerDataSource().getItem( | |||
grid.getSelectedRow()); | |||
Item item = grid.getContainerDataSource() | |||
.getItem(grid.getSelectedRow()); | |||
form.edit((BeanItem<ComplexPerson>) item); | |||
} | |||
}); | |||
grid.setEditorEnabled(true); | |||
grid.setSizeFull(); | |||
grid.getColumn("age") | |||
.getEditorField() | |||
.addValidator( | |||
new LegacyIntegerRangeValidator("Must be between 0 and 100", | |||
0, 100)); | |||
grid.getColumn("birthDate").setRenderer( | |||
new DateRenderer(DateFormat.getDateInstance(DateFormat.MEDIUM, | |||
Locale.US))); | |||
grid.getColumn("age").getEditorField().addValidator( | |||
new LegacyIntegerRangeValidator("Must be between 0 and 100", 0, | |||
100)); | |||
grid.getColumn("birthDate").setRenderer(new DateRenderer( | |||
DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.US))); | |||
addComponent(grid); | |||
getLayout().setExpandRatio(grid, 1); | |||
} |
@@ -1,5 +1,7 @@ | |||
package com.vaadin.tests.fieldgroup; | |||
import org.apache.commons.lang.StringEscapeUtils; | |||
import com.vaadin.data.fieldgroup.FieldGroup; | |||
import com.vaadin.data.util.BeanItem; | |||
import com.vaadin.legacy.data.Validator; | |||
@@ -10,7 +12,6 @@ import com.vaadin.tests.components.AbstractTestUI; | |||
import com.vaadin.ui.Button; | |||
import com.vaadin.ui.Label; | |||
import com.vaadin.ui.TextField; | |||
import org.apache.commons.lang.StringEscapeUtils; | |||
public class MultipleValidationErrors extends AbstractTestUI { | |||
@@ -39,8 +40,8 @@ public class MultipleValidationErrors extends AbstractTestUI { | |||
try { | |||
fieldGroup.commit(); | |||
} catch (FieldGroup.CommitException e) { | |||
if (e.getCause() != null | |||
&& e.getCause() instanceof Validator.InvalidValueException) { | |||
if (e.getCause() != null && e | |||
.getCause() instanceof Validator.InvalidValueException) { | |||
validationErrors.setValue(StringEscapeUtils | |||
.unescapeHtml(AbstractErrorMessage | |||
.getErrorMessageForException( |
@@ -14,8 +14,8 @@ import com.vaadin.ui.TextField; | |||
import com.vaadin.ui.VerticalLayout; | |||
import com.vaadin.ui.themes.Reindeer; | |||
public class SimpleLoginView extends CustomComponent implements View, | |||
Button.ClickListener { | |||
public class SimpleLoginView extends CustomComponent | |||
implements View, Button.ClickListener { | |||
public static final String NAME = "login"; | |||
@@ -33,8 +33,8 @@ public class SimpleLoginView extends CustomComponent implements View, | |||
user.setWidth("300px"); | |||
user.setRequired(true); | |||
user.setInputPrompt("Your username (eg. joe@email.com)"); | |||
user.addValidator(new LegacyEmailValidator( | |||
"Username must be an email address")); | |||
user.addValidator( | |||
new LegacyEmailValidator("Username must be an email address")); | |||
user.setInvalidAllowed(false); | |||
// Create the password input field | |||
@@ -50,7 +50,8 @@ public class SimpleLoginView extends CustomComponent implements View, | |||
// Add both to a panel | |||
VerticalLayout fields = new VerticalLayout(user, password, loginButton); | |||
fields.setCaption("Please login to access the application. (test@test.com/passw0rd)"); | |||
fields.setCaption( | |||
"Please login to access the application. (test@test.com/passw0rd)"); | |||
fields.setSpacing(true); | |||
fields.setMargin(new MarginInfo(true, true, true, false)); | |||
fields.setSizeUndefined(); | |||
@@ -72,8 +73,8 @@ public class SimpleLoginView extends CustomComponent implements View, | |||
/* | |||
* Validator for validating the passwords | |||
*/ | |||
private static final class PasswordValidator extends | |||
LegacyAbstractValidator<String> { | |||
private static final class PasswordValidator | |||
extends LegacyAbstractValidator<String> { | |||
public PasswordValidator() { | |||
super("The password provided is not valid"); |
@@ -185,7 +185,8 @@ public class Ticket1878 extends LegacyApplication { | |||
form = createForm(l1, "200px", "500px"); | |||
BeanItem<FormObject> item = new BeanItem<FormObject>(new FormObject()); | |||
form.setItemDataSource(item); | |||
for (Iterator<?> i = item.getItemPropertyIds().iterator(); i.hasNext();) { | |||
for (Iterator<?> i = item.getItemPropertyIds().iterator(); i | |||
.hasNext();) { | |||
Object property = i.next(); | |||
LegacyField<?> f = form.getField(property); | |||
@@ -197,7 +198,8 @@ public class Ticket1878 extends LegacyApplication { | |||
f.setCaption(null); | |||
} | |||
f.addValidator(new LegacyStringLengthValidator("Error", 10, 8, false)); | |||
f.addValidator( | |||
new LegacyStringLengthValidator("Error", 10, 8, false)); | |||
} | |||
// createLayout(l1, new | |||
// ExpandLayout(ExpandLayout.ORIENTATION_HORIZONTAL), | |||
@@ -277,8 +279,9 @@ public class Ticket1878 extends LegacyApplication { | |||
} | |||
String alignText = align ? "-A" : ""; | |||
String cWidth = componentWidth == null ? "" : " - " + componentWidth; | |||
Panel p = new Panel(type + "/" + dirText + alignText + " " + w + "x" | |||
+ h + cWidth, newLayout); | |||
Panel p = new Panel( | |||
type + "/" + dirText + alignText + " " + w + "x" + h + cWidth, | |||
newLayout); | |||
p.setWidth(w); | |||
p.setHeight(h); | |||
@@ -310,8 +313,8 @@ public class Ticket1878 extends LegacyApplication { | |||
newLayout.addComponent(tf); | |||
if (align) { | |||
((AlignmentHandler) newLayout).setComponentAlignment( | |||
tf, Alignment.BOTTOM_RIGHT); | |||
((AlignmentHandler) newLayout).setComponentAlignment(tf, | |||
Alignment.BOTTOM_RIGHT); | |||
} | |||
} | |||
} |
@@ -3,8 +3,8 @@ package com.vaadin.tests.tickets; | |||
import com.vaadin.data.util.MethodProperty; | |||
import com.vaadin.legacy.data.Validator; | |||
import com.vaadin.legacy.data.validator.LegacyCompositeValidator; | |||
import com.vaadin.legacy.data.validator.LegacyIntegerValidator; | |||
import com.vaadin.legacy.data.validator.LegacyCompositeValidator.CombinationMode; | |||
import com.vaadin.legacy.data.validator.LegacyIntegerValidator; | |||
import com.vaadin.server.LegacyApplication; | |||
import com.vaadin.ui.Button; | |||
import com.vaadin.ui.CheckBox; | |||
@@ -41,19 +41,21 @@ public class Ticket20 extends LegacyApplication { | |||
@Override | |||
public void validate(Object value) throws InvalidValueException { | |||
if (!isValid(value)) { | |||
throw new InvalidValueException(value | |||
+ " is not a non-negative number"); | |||
throw new InvalidValueException( | |||
value + " is not a non-negative number"); | |||
} | |||
} | |||
}); | |||
LegacyCompositeValidator v2 = new LegacyCompositeValidator(CombinationMode.OR, null); | |||
LegacyCompositeValidator v2 = new LegacyCompositeValidator( | |||
CombinationMode.OR, null); | |||
v2.addValidator(v); | |||
v2.addValidator(new Validator() { | |||
@Override | |||
public void validate(Object value) throws InvalidValueException { | |||
if (!"".equals("" + value)) { | |||
throw new InvalidValueException("Value is not empty string"); | |||
throw new InvalidValueException( | |||
"Value is not empty string"); | |||
} | |||
} | |||
}); | |||
@@ -69,8 +71,8 @@ public class Ticket20 extends LegacyApplication { | |||
mainWin.addComponent(b); | |||
} | |||
mainWin.addComponent(new Button("Validate integer", | |||
new Button.ClickListener() { | |||
mainWin.addComponent( | |||
new Button("Validate integer", new Button.ClickListener() { | |||
@Override | |||
public void buttonClick( | |||
com.vaadin.ui.Button.ClickEvent event) { |
@@ -67,8 +67,8 @@ public class Ticket736 extends LegacyApplication { | |||
f.getField("zip").addValidator( | |||
new LegacyIntegerValidator("'{0}' is not a number")); | |||
((AbstractComponent) f.getField("zip")).setDescription("Jepjep"); | |||
((AbstractComponent) f.getField("zip")).setIcon(new ThemeResource( | |||
"../runo/icons/16/folder.png")); | |||
((AbstractComponent) f.getField("zip")) | |||
.setIcon(new ThemeResource("../runo/icons/16/folder.png")); | |||
f.getField("state").addValidator(new IsValidState()); | |||
f.getField("name").setRequired(true); | |||
f.getField("street").setRequired(true); |
@@ -33,8 +33,8 @@ public class Ticket846 extends LegacyApplication { | |||
// tx.setIcon(new ThemeResource("icons/16/folder.png")); | |||
mainWin.addComponent(new Button("Validate integer", | |||
new Button.ClickListener() { | |||
mainWin.addComponent( | |||
new Button("Validate integer", new Button.ClickListener() { | |||
@Override | |||
public void buttonClick( | |||
com.vaadin.ui.Button.ClickEvent event) { |
@@ -17,10 +17,10 @@ package com.vaadin.tests.validation; | |||
import java.util.Set; | |||
import com.vaadin.legacy.ui.LegacyField; | |||
import com.vaadin.legacy.data.Validator; | |||
import com.vaadin.legacy.data.validator.LegacyStringLengthValidator; | |||
import com.vaadin.legacy.ui.LegacyAbstractField; | |||
import com.vaadin.legacy.ui.LegacyField; | |||
import com.vaadin.server.UserError; | |||
import com.vaadin.server.VaadinRequest; | |||
import com.vaadin.tests.components.AbstractTestUI; | |||
@@ -49,20 +49,22 @@ public class FieldErrorIndication extends AbstractTestUI { | |||
ComboBox comboBox = new ComboBox("ComboBox"); | |||
comboBox.addItem("ok"); | |||
comboBox.addItem("error"); | |||
comboBox.addValidator(new LegacyStringLengthValidator("fail", 0, 2, false)); | |||
comboBox.addValidator( | |||
new LegacyStringLengthValidator("fail", 0, 2, false)); | |||
comboBox.setValue("error"); | |||
ListSelect listSelect = new ListSelect("ListSelect"); | |||
listSelect.addItem("ok"); | |||
listSelect.addItem("error"); | |||
listSelect.addValidator(new LegacyStringLengthValidator("fail", 0, 2, false)); | |||
listSelect.addValidator( | |||
new LegacyStringLengthValidator("fail", 0, 2, false)); | |||
listSelect.setValue("error"); | |||
NativeSelect nativeSelect = new NativeSelect("NativeSelect"); | |||
nativeSelect.addItem("ok"); | |||
nativeSelect.addItem("error"); | |||
nativeSelect | |||
.addValidator(new LegacyStringLengthValidator("fail", 0, 2, false)); | |||
nativeSelect.addValidator( | |||
new LegacyStringLengthValidator("fail", 0, 2, false)); | |||
nativeSelect.setValue("error"); | |||
TwinColSelect twinColSelect = new TwinColSelect("TwinColSelect"); | |||
twinColSelect.addItem("ok"); |
@@ -3,12 +3,12 @@ package com.vaadin.tests.validation; | |||
import com.vaadin.legacy.data.Validator; | |||
import com.vaadin.legacy.data.validator.LegacyAbstractStringValidator; | |||
import com.vaadin.legacy.data.validator.LegacyCompositeValidator; | |||
import com.vaadin.legacy.data.validator.LegacyCompositeValidator.CombinationMode; | |||
import com.vaadin.legacy.data.validator.LegacyDoubleValidator; | |||
import com.vaadin.legacy.data.validator.LegacyEmailValidator; | |||
import com.vaadin.legacy.data.validator.LegacyIntegerValidator; | |||
import com.vaadin.legacy.data.validator.LegacyRegexpValidator; | |||
import com.vaadin.legacy.data.validator.LegacyStringLengthValidator; | |||
import com.vaadin.legacy.data.validator.LegacyCompositeValidator.CombinationMode; | |||
import com.vaadin.tests.components.TestBase; | |||
import com.vaadin.ui.Button; | |||
import com.vaadin.ui.Button.ClickEvent; | |||
@@ -37,7 +37,8 @@ public class TestValidators extends TestBase { | |||
// simple validators | |||
TextField tf = new TextField("A field, must contain 1-2 chars"); | |||
tf.addValidator(new LegacyStringLengthValidator("Invalid length", 1, 2, false)); | |||
tf.addValidator( | |||
new LegacyStringLengthValidator("Invalid length", 1, 2, false)); | |||
tf.setRequired(true); | |||
tf.setValue("ab"); | |||
form.addField("a", tf); | |||
@@ -67,7 +68,8 @@ public class TestValidators extends TestBase { | |||
// regular expressions | |||
tf = new TextField("A field, must match the regular expression a.*b.*c"); | |||
tf = new TextField( | |||
"A field, must match the regular expression a.*b.*c"); | |||
tf.addValidator(new LegacyRegexpValidator("a.*b.*c", | |||
"{0} does not match the regular expression")); | |||
tf.setValue("aagsabeqgc"); | |||
@@ -97,10 +99,12 @@ public class TestValidators extends TestBase { | |||
// TODO CompositeValidator | |||
tf = new TextField( | |||
"A field, must be a floating point number with 4-5 chars"); | |||
LegacyCompositeValidator cv = new LegacyCompositeValidator(CombinationMode.AND, | |||
LegacyCompositeValidator cv = new LegacyCompositeValidator( | |||
CombinationMode.AND, | |||
"The field must contain a floating point number with 4-5 characters"); | |||
cv.addValidator(new LegacyStringLengthValidator( | |||
"String length of '{0}' should be 4-5 characters", 4, 5, false)); | |||
"String length of '{0}' should be 4-5 characters", 4, 5, | |||
false)); | |||
cv.addValidator(new LegacyDoubleValidator( | |||
"{0} must be a floating point number")); | |||
tf.addValidator(cv); | |||
@@ -112,7 +116,8 @@ public class TestValidators extends TestBase { | |||
cv = new LegacyCompositeValidator(CombinationMode.OR, | |||
"The field must contain a floating point or with 4-5 characters"); | |||
cv.addValidator(new LegacyStringLengthValidator( | |||
"String length of '{0}' should be 4-5 characters", 4, 5, false)); | |||
"String length of '{0}' should be 4-5 characters", 4, 5, | |||
false)); | |||
cv.addValidator(new LegacyDoubleValidator( | |||
"{0} must be a floating point number")); | |||
tf.addValidator(cv); |