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

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

Go to download

JPMS Module-Info's for a few of the Jakarta Libraries. These will be removed as time goes by

There is a newer version: 62
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;
import org.hibernate.validator.metadata.BeanMetaDataClassNormalizer;

/**
 * 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 BeanMetaDataClassNormalizer beanMetaDataClassNormalizer; 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, BeanMetaDataClassNormalizer beanMetaDataClassNormalizer, ValidationOrderGenerator validationOrderGenerator, List optionalMetaDataProviders, MethodValidationConfiguration methodValidationConfiguration) { this.constraintCreationContext = constraintCreationContext; this.executableHelper = executableHelper; this.parameterNameProvider = parameterNameProvider; this.beanMetaDataClassNormalizer = beanMetaDataClassNormalizer; 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 // TODO Some of these casts from BeanMetadata to BeanMetadata may not be safe. // Maybe we should return a wrapper around the BeanMetadata if the normalized class is different from beanClass? @SuppressWarnings("unchecked") public BeanMetaData getBeanMetaData(Class beanClass) { Contracts.assertNotNull( beanClass, MESSAGES.beanTypeCannotBeNull() ); Class normalizedBeanClass = beanMetaDataClassNormalizer.normalize( beanClass ); // First, let's do a simple lookup as it's the default case BeanMetaData beanMetaData = (BeanMetaData) beanMetaDataCache.get( normalizedBeanClass ); if ( beanMetaData != null ) { return (BeanMetaData) beanMetaData; } beanMetaData = createBeanMetaData( normalizedBeanClass ); BeanMetaData previousBeanMetaData = (BeanMetaData) beanMetaDataCache.putIfAbsent( normalizedBeanClass, beanMetaData ); // we return the previous value if not null if ( previousBeanMetaData != null ) { return (BeanMetaData) previousBeanMetaData; } return (BeanMetaData) 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