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

nl._42.jarb.constraint.metadata.BeanConstraintDescriptor Maven / Gradle / Ivy

There is a newer version: 7.0.0
Show newest version
package nl._42.jarb.constraint.metadata;

import static nl._42.jarb.utils.Asserts.notNull;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.Embeddable;

import nl._42.jarb.constraint.metadata.enhance.PropertyConstraintEnhancer;

import nl._42.jarb.constraint.metadata.enhance.PropertyConstraintEnhancer;
import nl._42.jarb.utils.bean.BeanRegistry;
import nl._42.jarb.utils.bean.MapBeanRegistry;
import nl._42.jarb.utils.bean.PropertyReference;
import org.springframework.beans.BeanUtils;
import org.springframework.util.ReflectionUtils;

/**
 * Generates bean constraint metadata.
 * 
 * @author Jeroen van Schagen
 * @since 4-6-2011
 */
public class BeanConstraintDescriptor {

    /**
     * Enhances the property descriptions.
     */
    private final List enhancers = new ArrayList();

    /**
     * Registry of all supported beans.
     */
    private BeanRegistry beanRegistry = new MapBeanRegistry();

    /**
     * Generate all beans constraint meta data.
     * 
     * @return the beans constraint meta data
     */
    public List describeAll() {
        List descriptions = new ArrayList();
        for (Class beanClass : beanRegistry.getAll()) {
            descriptions.add(describeBean(beanClass));
        }
        return descriptions;
    }

    /**
     * Generate bean constraint meta data.
     * 
     * @param beanType class of the bean
     * @return bean constraint meta data
     */
    public BeanConstraintDescription describeBean(String beanType) {
        Class beanClass = beanRegistry.getBeanClass(beanType);
        return describeBean(beanClass);
    }

    /**
     * Generate bean constraint meta data.
     * 
     * @param beanClass class of the bean
     * @return bean constraint meta data
     */
    public BeanConstraintDescription describeBean(Class beanClass) {
        BeanConstraintDescription beanDescription = new BeanConstraintDescription(beanClass);
        for (PropertyDescriptor propertyDescriptor : BeanUtils.getPropertyDescriptors(beanClass)) {
            Field field = ReflectionUtils.findField(beanClass, propertyDescriptor.getName());
            if (field != null) {
                if (field.getType().isAnnotationPresent(Embeddable.class)) {
                    describeEmbeddable(beanDescription, beanClass, field.getType(), propertyDescriptor.getName());
                } else {
                    beanDescription.addProperty(describeProperty(beanClass, propertyDescriptor, propertyDescriptor.getName()));
                }
            }
        }
        return beanDescription;
    }

    /**
     * Describe the constraints of a specific property.
     * 
     * @param beanClass type of bean that contains the property
     * @param descriptor plain property description from java
     * @param path the path to the property from the beanClass.
     * @return property constraint description
     */
    private PropertyConstraintDescription describeProperty(Class beanClass, PropertyDescriptor descriptor, String path) {
        PropertyConstraintDescription description = doDescribeProperty(beanClass, descriptor, path);
        for (PropertyConstraintEnhancer enhancer : enhancers) {
            enhancer.enhance(description);
        }
        return description;
    }

    /**
     * Construct a new {@link PropertyConstraintDescription} for some property.
     * 
     * @param beanClass type of bean that contains the property
     * @param descriptor plain property description from java
     * @param path the path to the property from the beanClass.
     * @return new property constraint description
     */
    private PropertyConstraintDescription doDescribeProperty(Class beanClass, PropertyDescriptor descriptor, String path) {
        PropertyReference reference = new PropertyReference(beanClass, path);
        return new PropertyConstraintDescription(reference, descriptor.getPropertyType());
    }

    /**
     * Take an embedable and walk through each property and add it to the beanDescription.
     *
     * @param beanDescription Constains the current descriptions for the bean.
     * @param beanClass The Bean which is described
     * @param embeddable The Embeddable which fields needs to be added to the beanDescription.
     * @param path The current path from the bean to the embeddable field.
     */
    private void describeEmbeddable(BeanConstraintDescription beanDescription, Class beanClass , Class embeddable, String path) {
        for (PropertyDescriptor propertyDescriptor : BeanUtils.getPropertyDescriptors(embeddable)) {
            Class klass = propertyDescriptor.getPropertyType();

            if (klass != null) {
                if (klass.isAnnotationPresent(Embeddable.class)) {
                    describeEmbeddable(beanDescription, beanClass, klass, path + "." + propertyDescriptor.getName());
                } else {
                    String fullPath = path + "." + propertyDescriptor.getName();
                    beanDescription.addProperty(describeProperty(beanClass, propertyDescriptor, fullPath));
                }
            }
        }
    }

    /**
     * Register a property constraint enhancer to this bean constraint accessor.
     * Whenever a new bean is described, the provided enhancer will be used.
     * 
     * @param enhancer enhancer used to improve property constraint descriptions
     * @return this bean descriptor, used for chaining
     */
    public BeanConstraintDescriptor register(PropertyConstraintEnhancer enhancer) {
        enhancers.add(notNull(enhancer, "Cannot add a null property constraint enhancer"));
        return this;
    }
    
    public void setBeanRegistry(BeanRegistry beanRegistry) {
        this.beanRegistry = beanRegistry;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy