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

org.hibernate.validator.internal.metadata.PredefinedScopeBeanMetaDataManager Maven / Gradle / Ivy

There is a newer version: 8.0.1.Final
Show newest version
/*
 * Hibernate Validator, declare and validate application constraints
 *
 * License: Apache License, Version 2.0
 * See the license.txt file in the root directory or .
 */
package org.hibernate.validator.internal.metadata;

import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList;

import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.hibernate.validator.internal.engine.ConstraintCreationContext;
import org.hibernate.validator.internal.engine.MethodValidationConfiguration;
import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator;
import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData;
import org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataBuilder;
import org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataImpl;
import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptions;
import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl;
import org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider;
import org.hibernate.validator.internal.metadata.provider.MetaDataProvider;
import org.hibernate.validator.internal.metadata.raw.BeanConfiguration;
import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper;
import org.hibernate.validator.internal.util.CollectionHelper;
import org.hibernate.validator.internal.util.ExecutableHelper;
import org.hibernate.validator.internal.util.ExecutableParameterNameProvider;
import org.hibernate.validator.internal.util.classhierarchy.ClassHierarchyHelper;
import org.hibernate.validator.internal.util.classhierarchy.Filters;
import org.hibernate.validator.internal.util.logging.Log;
import org.hibernate.validator.internal.util.logging.LoggerFactory;
import org.hibernate.validator.metadata.BeanMetaDataClassNormalizer;

public class PredefinedScopeBeanMetaDataManager implements BeanMetaDataManager {

	private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() );

	private final BeanMetaDataClassNormalizer beanMetaDataClassNormalizer;

	/**
	 * Used to cache the constraint meta data for validated entities
	 */
	private final Map, BeanMetaData> beanMetaDataMap;

	public PredefinedScopeBeanMetaDataManager(ConstraintCreationContext constraintCreationContext,
			ExecutableHelper executableHelper,
			ExecutableParameterNameProvider parameterNameProvider,
			JavaBeanHelper javaBeanHelper,
			ValidationOrderGenerator validationOrderGenerator,
			List optionalMetaDataProviders,
			MethodValidationConfiguration methodValidationConfiguration,
			BeanMetaDataClassNormalizer beanMetaDataClassNormalizer,
			Set> beanClassesToInitialize) {
		AnnotationProcessingOptions annotationProcessingOptions = getAnnotationProcessingOptionsFromNonDefaultProviders( optionalMetaDataProviders );
		AnnotationMetaDataProvider defaultProvider = new AnnotationMetaDataProvider(
				constraintCreationContext,
				javaBeanHelper,
				annotationProcessingOptions
		);

		List metaDataProviders = new ArrayList<>( optionalMetaDataProviders.size() + 1 );
		// We add the annotation based metadata provider at the first position so that the entire metadata model is assembled
		// first.
		// The other optional metadata providers will then contribute their additional metadata to the preexisting model.
		// This helps to mitigate issues like HV-1450.
		metaDataProviders.add( defaultProvider );
		metaDataProviders.addAll( optionalMetaDataProviders );

		Map, BeanMetaData> tmpBeanMetadataMap = new HashMap<>();

		for ( Class validatedClass : beanClassesToInitialize ) {
			@SuppressWarnings("unchecked")
			List> classHierarchy = (List>) (Object) ClassHierarchyHelper.getHierarchy( validatedClass, Filters.excludeInterfaces() );

			// note that the hierarchy also contains the initial class
			for ( Class hierarchyElement : classHierarchy ) {
				tmpBeanMetadataMap.put( beanMetaDataClassNormalizer.normalize( hierarchyElement ),
						createBeanMetaData( constraintCreationContext, executableHelper, parameterNameProvider,
								javaBeanHelper, validationOrderGenerator, optionalMetaDataProviders, methodValidationConfiguration,
								metaDataProviders, hierarchyElement ) );
			}
		}

		this.beanMetaDataMap = CollectionHelper.toImmutableMap( tmpBeanMetadataMap );

		this.beanMetaDataClassNormalizer = beanMetaDataClassNormalizer;
	}

	@SuppressWarnings("unchecked")
	@Override
	public  BeanMetaData getBeanMetaData(Class beanClass) {
		BeanMetaData beanMetaData = (BeanMetaData) beanMetaDataMap.get( beanMetaDataClassNormalizer.normalize( beanClass ) );
		if ( beanMetaData == null ) {
			throw LOG.uninitializedBeanMetaData( beanClass );
		}
		return beanMetaData;
	}

	@Override
	public void clear() {
		beanMetaDataMap.clear();
	}

	/**
	 * Creates a {@link org.hibernate.validator.internal.metadata.aggregated.BeanMetaData} containing the meta data from all meta
	 * data providers for the given type and its hierarchy.
	 *
	 * @param  The type of interest.
	 * @param clazz The type's class.
	 *
	 * @return A bean meta data object for the given type.
	 */
	private static  BeanMetaDataImpl createBeanMetaData(ConstraintCreationContext constraintCreationContext,
			ExecutableHelper executableHelper,
			ExecutableParameterNameProvider parameterNameProvider,
			JavaBeanHelper javaBeanHelper,
			ValidationOrderGenerator validationOrderGenerator,
			List optionalMetaDataProviders,
			MethodValidationConfiguration methodValidationConfiguration,
			List metaDataProviders,
			Class clazz) {
		BeanMetaDataBuilder builder = BeanMetaDataBuilder.getInstance(
				constraintCreationContext, executableHelper, parameterNameProvider,
				validationOrderGenerator, clazz, methodValidationConfiguration );

		for ( MetaDataProvider provider : metaDataProviders ) {
			for ( BeanConfiguration beanConfiguration : getBeanConfigurationForHierarchy( provider, clazz ) ) {
				builder.add( beanConfiguration );
			}
		}

		return builder.build();
	}

	/**
	 * @return returns the annotation ignores from the non annotation based meta data providers
	 */
	private static AnnotationProcessingOptions getAnnotationProcessingOptionsFromNonDefaultProviders(List optionalMetaDataProviders) {
		AnnotationProcessingOptions options = new AnnotationProcessingOptionsImpl();
		for ( MetaDataProvider metaDataProvider : optionalMetaDataProviders ) {
			options.merge( metaDataProvider.getAnnotationProcessingOptions() );
		}

		return options;
	}

	/**
	 * Returns a list with the configurations for all types contained in the given type's hierarchy (including
	 * implemented interfaces) starting at the specified type.
	 *
	 * @param beanClass The type of interest.
	 * @param  The type of the class to get the configurations for.
	 * @return A set with the configurations for the complete hierarchy of the given type. May be empty, but never
	 * {@code null}.
	 */
	private static  List> getBeanConfigurationForHierarchy(MetaDataProvider provider, Class beanClass) {
		List> configurations = newArrayList();

		for ( Class clazz : ClassHierarchyHelper.getHierarchy( beanClass ) ) {
			BeanConfiguration configuration = provider.getBeanConfiguration( clazz );
			if ( configuration != null ) {
				configurations.add( configuration );
			}
		}

		return configurations;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy