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

org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl 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 static org.hibernate.validator.internal.util.ConcurrentReferenceHashMap.Option.IDENTITY_COMPARISONS;
import static org.hibernate.validator.internal.util.ConcurrentReferenceHashMap.ReferenceType.SOFT;
import static org.hibernate.validator.internal.util.logging.Messages.MESSAGES;

import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;

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.ConcurrentReferenceHashMap;
import org.hibernate.validator.internal.util.Contracts;
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.stereotypes.Immutable;

/**
 * This manager is in charge of providing all constraint related meta data
 * required by the validation engine.
 * 

* Actual retrieval of meta data is delegated to {@link MetaDataProvider} * implementations which load meta-data based e.g. based on annotations or XML. *

* For performance reasons a cache is used which stores all meta data once * loaded for repeated retrieval. Upon initialization this cache is populated * with meta data provided by the given eager providers. If the cache * doesn't contain the meta data for a requested type it will be retrieved on * demand using the annotation based provider. * * @author Gunnar Morling * @author Chris Beckey <[email protected]> * @author Guillaume Smet */ public class BeanMetaDataManagerImpl implements BeanMetaDataManager { /** * The default initial capacity for this cache. */ private static final int DEFAULT_INITIAL_CAPACITY = 16; /** * The default load factor for this cache. */ private static final float DEFAULT_LOAD_FACTOR = 0.75f; /** * The default concurrency level for this cache. */ private static final int DEFAULT_CONCURRENCY_LEVEL = 16; /** * Additional metadata providers used for meta data retrieval if * the XML and/or programmatic configuration is used. */ @Immutable private final List metaDataProviders; /** * The constraint creation context containing all the helpers necessary to the constraint creation. */ private final ConstraintCreationContext constraintCreationContext; private final ExecutableParameterNameProvider parameterNameProvider; /** * Used to cache the constraint meta data for validated entities */ private final ConcurrentReferenceHashMap, BeanMetaData> beanMetaDataCache; /** * Used for resolving type parameters. Thread-safe. */ private final ExecutableHelper executableHelper; private final ValidationOrderGenerator validationOrderGenerator; /** * the three properties in this field affect the invocation of rules associated to section 4.5.5 * of the specification. By default they are all false, if true they allow * for relaxation of the Liskov Substitution Principal. */ private final MethodValidationConfiguration methodValidationConfiguration; public BeanMetaDataManagerImpl(ConstraintCreationContext constraintCreationContext, ExecutableHelper executableHelper, ExecutableParameterNameProvider parameterNameProvider, JavaBeanHelper javaBeanHelper, ValidationOrderGenerator validationOrderGenerator, List optionalMetaDataProviders, MethodValidationConfiguration methodValidationConfiguration) { this.constraintCreationContext = constraintCreationContext; this.executableHelper = executableHelper; this.parameterNameProvider = parameterNameProvider; this.validationOrderGenerator = validationOrderGenerator; this.methodValidationConfiguration = methodValidationConfiguration; this.beanMetaDataCache = new ConcurrentReferenceHashMap<>( DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL, SOFT, SOFT, EnumSet.of( IDENTITY_COMPARISONS ) ); AnnotationProcessingOptions annotationProcessingOptions = getAnnotationProcessingOptionsFromNonDefaultProviders( optionalMetaDataProviders ); AnnotationMetaDataProvider defaultProvider = new AnnotationMetaDataProvider( constraintCreationContext, javaBeanHelper, annotationProcessingOptions ); List tmpMetaDataProviders = 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. tmpMetaDataProviders.add( defaultProvider ); tmpMetaDataProviders.addAll( optionalMetaDataProviders ); this.metaDataProviders = CollectionHelper.toImmutableList( tmpMetaDataProviders ); } @Override @SuppressWarnings("unchecked") public BeanMetaData getBeanMetaData(Class beanClass) { Contracts.assertNotNull( beanClass, MESSAGES.beanTypeCannotBeNull() ); BeanMetaData beanMetaData = (BeanMetaData) beanMetaDataCache.computeIfAbsent( beanClass, bc -> createBeanMetaData( bc ) ); return beanMetaData; } @Override public void clear() { beanMetaDataCache.clear(); } public int numberOfCachedBeanMetaDataInstances() { return beanMetaDataCache.size(); } /** * 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 BeanMetaDataImpl createBeanMetaData(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 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 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