- /*
- * Copyright 2000-2018 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.io.Serializable;
- import java.util.Locale;
- import java.util.Objects;
- import java.util.Optional;
- import java.util.Set;
-
- 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.ValidationResult;
- import com.vaadin.data.Validator;
- import com.vaadin.data.ValueContext;
- import com.vaadin.data.util.BeanUtil;
-
- /**
- * 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 (for instance
- * <a href="http://hibernate.org/validator/">Hibernate Validator</a> or
- * <a href="http://bval.apache.org/">Apache BVal</a>) must be present on the
- * project classpath when using bean validation. Specification versions 1.0 and
- * 1.1 are supported.
- *
- * @author Vaadin Ltd.
- *
- * @since 8.0
- */
- public class BeanValidator implements Validator<Object> {
-
- private static final class ContextImpl implements Context, Serializable {
-
- private final ConstraintViolation<?> violation;
-
- private ContextImpl(ConstraintViolation<?> violation) {
- this.violation = violation;
- }
-
- @Override
- public ConstraintDescriptor<?> getConstraintDescriptor() {
- return violation.getConstraintDescriptor();
- }
-
- @Override
- public Object getValidatedValue() {
- return violation.getInvalidValue();
- }
-
- @Override
- public <T> T unwrap(Class<T> type) {
- return violation.unwrap(type);
- }
- }
-
- private String propertyName;
- private Class<?> beanType;
-
- /**
- * 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
- * @throws IllegalStateException
- * if {@link BeanUtil#checkBeanValidationAvailable()} returns
- * false
- */
- public BeanValidator(Class<?> beanType, String propertyName) {
- if (!BeanUtil.checkBeanValidationAvailable()) {
- throw new IllegalStateException("Cannot create a "
- + BeanValidator.class.getSimpleName()
- + ": a JSR-303 Bean Validation implementation not found on the classpath");
- }
- Objects.requireNonNull(beanType, "bean class cannot be null");
- Objects.requireNonNull(propertyName, "property name cannot be null");
-
- this.beanType = beanType;
- this.propertyName = propertyName;
- }
-
- /**
- * 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.
- *
- * @param value
- * the input value to validate
- * @param context
- * the value context for validation
- * @return the validation result
- */
- @Override
- public ValidationResult apply(final Object value, ValueContext context) {
- Set<? extends ConstraintViolation<?>> violations = getJavaxBeanValidator()
- .validateValue(beanType, propertyName, value);
-
- Locale locale = context.getLocale().orElse(Locale.getDefault());
-
- Optional<ValidationResult> result = violations.stream()
- .map(violation -> ValidationResult
- .error(getMessage(violation, locale)))
- .findFirst();
- return result.orElse(ValidationResult.ok());
- }
-
- @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() {
- return LazyFactoryInitializer.FACTORY;
- }
-
- /**
- * Returns a shared JSR-303 validator instance to use.
- *
- * @return the validator to use
- */
- public 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 violation
- * the constraint violation
- * @param locale
- * the used locale
- * @return the localized error message
- */
- protected String getMessage(ConstraintViolation<?> violation,
- Locale locale) {
- return getJavaxBeanValidatorFactory().getMessageInterpolator()
- .interpolate(violation.getMessageTemplate(),
- createContext(violation), locale);
- }
-
- /**
- * Creates a simple message interpolation context based on the given
- * constraint violation.
- *
- * @param violation
- * the constraint violation
- * @return the message interpolation context
- */
- protected Context createContext(ConstraintViolation<?> violation) {
- return new ContextImpl(violation);
- }
-
- private static class LazyFactoryInitializer implements Serializable {
- private static final ValidatorFactory FACTORY = getFactory();
-
- private static ValidatorFactory getFactory() {
- return Validation.buildDefaultValidatorFactory();
- }
-
- private LazyFactoryInitializer() {
- }
- }
- }
|