All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.vaadin.data.BeanValidationBinder Maven / Gradle / Ivy

There is a newer version: 8.27.3
Show newest version
/*
 * Copyright (C) 2000-2024 Vaadin Ltd
 *
 * This program is available under Vaadin Commercial License and Service Terms.
 *
 * See  for the full
 * license.
 */
package com.vaadin.data;

import javax.validation.metadata.BeanDescriptor;
import javax.validation.metadata.ConstraintDescriptor;
import javax.validation.metadata.PropertyDescriptor;

import com.vaadin.data.BeanPropertySet.NestedBeanPropertyDefinition;
import com.vaadin.data.util.BeanUtil;
import com.vaadin.data.validator.BeanValidator;

/**
 * @author Vaadin Ltd
 * @see Binder
 * @see HasValue
 *
 * @since 8.0
 */
public class BeanValidationBinder extends Binder {

    private final Class beanType;

    private RequiredFieldConfigurator requiredConfigurator = RequiredFieldConfigurator.DEFAULT;

    /**
     * Creates a new binder that uses reflection based on the provided bean type
     * to resolve bean properties. It assumes that JSR-303 bean validation
     * implementation is present on the classpath. If there is no such
     * implementation available then {@link Binder} class should be used instead
     * (this constructor will throw an exception). Otherwise
     * {@link BeanValidator} is added to each binding that is defined using a
     * property name.
     *
     * @param beanType
     *            the bean type to use, not null
     */
    public BeanValidationBinder(Class beanType) {
        this(beanType, false);
    }

    /**
     * Creates a new binder that uses reflection based on the provided bean type
     * to resolve bean properties. It assumes that JSR-303 bean validation
     * implementation is present on the classpath. If there is no such
     * implementation available then {@link Binder} class should be used instead
     * (this constructor will throw an exception). Otherwise
     * {@link BeanValidator} is added to each binding that is defined using a
     * property name.
     *
     * @param beanType
     *            the bean type to use, not {@code null}
     * @param scanNestedDefinitions
     *            if {@code true}, scan for nested property definitions as well
     * 
     * @since 8.10
     */
    public BeanValidationBinder(Class beanType,
            boolean scanNestedDefinitions) {
        super(beanType, scanNestedDefinitions);
        if (!BeanUtil.checkBeanValidationAvailable()) {
            throw new IllegalStateException(BeanValidationBinder.class
                    .getSimpleName()
                    + " cannot be used because a JSR-303 Bean Validation "
                    + "implementation not found on the classpath or could not be initialized. Use "
                    + Binder.class.getSimpleName() + " instead");
        }
        this.beanType = beanType;
    }

    /**
     * Sets a logic which allows to configure require indicator via
     * {@link HasValue#setRequiredIndicatorVisible(boolean)} based on property
     * descriptor.
     * 

* Required indicator configuration will not be used at all if * {@code configurator} is null. *

* By default the {@link RequiredFieldConfigurator#DEFAULT} configurator is * used. * * @param configurator * required indicator configurator, may be {@code null} */ public void setRequiredConfigurator( RequiredFieldConfigurator configurator) { requiredConfigurator = configurator; } /** * Gets field required indicator configuration logic. * * @see #setRequiredConfigurator(RequiredFieldConfigurator) * * @return required indicator configurator, may be {@code null} */ public RequiredFieldConfigurator getRequiredConfigurator() { return requiredConfigurator; } @Override protected BindingBuilder configureBinding( BindingBuilder binding, PropertyDefinition definition) { Class actualBeanType = findBeanType(beanType, definition); BeanValidator validator = new BeanValidator(actualBeanType, definition.getTopLevelName()); if (requiredConfigurator != null) { configureRequired(binding, definition, validator); } return binding.withValidator(validator); } /** * Finds the bean type containing the property the given definition refers * to. * * @param beanType * the root beanType * @param definition * the definition for the property * @return the bean type containing the given property */ @SuppressWarnings({ "rawtypes" }) private Class findBeanType(Class beanType, PropertyDefinition definition) { if (definition instanceof NestedBeanPropertyDefinition) { return ((NestedBeanPropertyDefinition) definition).getParent() .getType(); } else { // Non nested properties must be defined in the main type return beanType; } } private void configureRequired(BindingBuilder binding, PropertyDefinition definition, BeanValidator validator) { assert requiredConfigurator != null; Class propertyHolderType = definition.getPropertyHolderType(); BeanDescriptor descriptor = validator.getJavaxBeanValidator() .getConstraintsForClass(propertyHolderType); PropertyDescriptor propertyDescriptor = descriptor .getConstraintsForProperty(definition.getTopLevelName()); if (propertyDescriptor == null) { return; } if (propertyDescriptor.getConstraintDescriptors().stream() .map(ConstraintDescriptor::getAnnotation) .anyMatch(requiredConfigurator)) { binding.getField().setRequiredIndicatorVisible(true); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy