123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- /*
- * 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;
- }
- }
|