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

org.hibernate.validator.internal.metadata.provider.ProgrammaticMetaDataProvider Maven / Gradle / Ivy

Go to download

JSR 380's RI, Hibernate Validator version ${hibernate-validator.version} and its dependencies repackaged as OSGi bundle

There is a newer version: 5.1.0
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.provider;

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

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

import org.hibernate.validator.internal.cfg.context.DefaultConstraintMapping;
import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager;
import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptions;
import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl;
import org.hibernate.validator.internal.metadata.core.ConstraintHelper;
import org.hibernate.validator.internal.metadata.raw.BeanConfiguration;
import org.hibernate.validator.internal.util.CollectionHelper;
import org.hibernate.validator.internal.util.Contracts;
import org.hibernate.validator.internal.util.TypeResolutionHelper;
import org.hibernate.validator.internal.util.logging.Log;
import org.hibernate.validator.internal.util.logging.LoggerFactory;
import org.hibernate.validator.internal.util.stereotypes.Immutable;

/**
 * A {@link MetaDataProvider} based on the programmatic constraint API.
 *
 * @author Gunnar Morling
 */
public class ProgrammaticMetaDataProvider implements MetaDataProvider {

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

	// cached against the fqcn of a class. not a class instance itself (HV-479)
	@Immutable
	private final Map> configuredBeans;
	private final AnnotationProcessingOptions annotationProcessingOptions;

	public ProgrammaticMetaDataProvider(ConstraintHelper constraintHelper,
										TypeResolutionHelper typeResolutionHelper,
										ValueExtractorManager valueExtractorManager,
										Set constraintMappings) {
		Contracts.assertNotNull( constraintMappings );

		configuredBeans = CollectionHelper.toImmutableMap(
				createBeanConfigurations( constraintMappings, constraintHelper, typeResolutionHelper, valueExtractorManager )
		);

		assertUniquenessOfConfiguredTypes( constraintMappings );
		annotationProcessingOptions = mergeAnnotationProcessingOptions( constraintMappings );
	}

	private static void assertUniquenessOfConfiguredTypes(Set mappings) {
		Set> allConfiguredTypes = newHashSet();

		for ( DefaultConstraintMapping constraintMapping : mappings ) {
			for ( Class configuredType : constraintMapping.getConfiguredTypes() ) {
				if ( allConfiguredTypes.contains( configuredType ) ) {
					throw LOG.getBeanClassHasAlreadyBeConfiguredViaProgrammaticApiException( configuredType );
				}
			}

			allConfiguredTypes.addAll( constraintMapping.getConfiguredTypes() );
		}
	}

	private static Map> createBeanConfigurations(Set mappings, ConstraintHelper constraintHelper,
			TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager) {
		final Map> configuredBeans = new HashMap<>();
		for ( DefaultConstraintMapping mapping : mappings ) {
			Set> beanConfigurations = mapping.getBeanConfigurations( constraintHelper, typeResolutionHelper,
					valueExtractorManager );

			for ( BeanConfiguration beanConfiguration : beanConfigurations ) {
				configuredBeans.put( beanConfiguration.getBeanClass().getName(), beanConfiguration );
			}
		}
		return configuredBeans;
	}

	/**
	 * Creates a single merged {@code AnnotationProcessingOptions} in case multiple programmatic mappings are provided.
	 * 

* Note that it is made sure at this point that no element (type, property, method etc.) is configured more than once within * all the given contexts. So the "merge" pulls together the information for all configured elements, but it will never * merge several configurations for one given element. * * @param contexts set of mapping contexts providing annotation processing options to be merged * * @return a single annotation processing options object */ private static AnnotationProcessingOptions mergeAnnotationProcessingOptions(Set mappings) { // if we only have one mapping we can return the context of just this mapping if ( mappings.size() == 1 ) { return mappings.iterator().next().getAnnotationProcessingOptions(); } AnnotationProcessingOptions options = new AnnotationProcessingOptionsImpl(); for ( DefaultConstraintMapping mapping : mappings ) { options.merge( mapping.getAnnotationProcessingOptions() ); } return options; } @Override @SuppressWarnings("unchecked") public BeanConfiguration getBeanConfiguration(Class beanClass) { return (BeanConfiguration) configuredBeans.get( beanClass.getName() ); } @Override public AnnotationProcessingOptions getAnnotationProcessingOptions() { return annotationProcessingOptions; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy