1
7 package org.hibernate.validator.internal.metadata.provider;
8
9 import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet;
10
11 import java.lang.invoke.MethodHandles;
12 import java.util.HashMap;
13 import java.util.Map;
14 import java.util.Set;
15
16 import org.hibernate.validator.internal.cfg.context.DefaultConstraintMapping;
17 import org.hibernate.validator.internal.engine.ConstraintCreationContext;
18 import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptions;
19 import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl;
20 import org.hibernate.validator.internal.metadata.raw.BeanConfiguration;
21 import org.hibernate.validator.internal.util.CollectionHelper;
22 import org.hibernate.validator.internal.util.Contracts;
23 import org.hibernate.validator.internal.util.logging.Log;
24 import org.hibernate.validator.internal.util.logging.LoggerFactory;
25 import org.hibernate.validator.internal.util.stereotypes.Immutable;
26
27
32 public class ProgrammaticMetaDataProvider implements MetaDataProvider {
33
34 private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() );
35
36
37 @Immutable
38 private final Map<String, BeanConfiguration<?>> configuredBeans;
39 private final AnnotationProcessingOptions annotationProcessingOptions;
40
41 public ProgrammaticMetaDataProvider(ConstraintCreationContext constraintCreationContext,
42 Set<DefaultConstraintMapping> constraintMappings) {
43 Contracts.assertNotNull( constraintMappings );
44
45 configuredBeans = CollectionHelper.toImmutableMap(
46 createBeanConfigurations( constraintMappings, constraintCreationContext )
47 );
48
49 assertUniquenessOfConfiguredTypes( constraintMappings );
50 annotationProcessingOptions = mergeAnnotationProcessingOptions( constraintMappings );
51 }
52
53 private static void assertUniquenessOfConfiguredTypes(Set<DefaultConstraintMapping> mappings) {
54 Set<Class<?>> allConfiguredTypes = newHashSet();
55
56 for ( DefaultConstraintMapping constraintMapping : mappings ) {
57 for ( Class<?> configuredType : constraintMapping.getConfiguredTypes() ) {
58 if ( allConfiguredTypes.contains( configuredType ) ) {
59 throw LOG.getBeanClassHasAlreadyBeConfiguredViaProgrammaticApiException( configuredType );
60 }
61 }
62
63 allConfiguredTypes.addAll( constraintMapping.getConfiguredTypes() );
64 }
65 }
66
67 private static Map<String, BeanConfiguration<?>> createBeanConfigurations(Set<DefaultConstraintMapping> mappings,
68 ConstraintCreationContext constraintCreationContext) {
69 final Map<String, BeanConfiguration<?>> configuredBeans = new HashMap<>();
70 for ( DefaultConstraintMapping mapping : mappings ) {
71 Set<BeanConfiguration<?>> beanConfigurations = mapping.getBeanConfigurations( constraintCreationContext );
72
73 for ( BeanConfiguration<?> beanConfiguration : beanConfigurations ) {
74 configuredBeans.put( beanConfiguration.getBeanClass().getName(), beanConfiguration );
75 }
76 }
77 return configuredBeans;
78 }
79
80
91 private static AnnotationProcessingOptions mergeAnnotationProcessingOptions(Set<DefaultConstraintMapping> mappings) {
92
93 if ( mappings.size() == 1 ) {
94 return mappings.iterator().next().getAnnotationProcessingOptions();
95 }
96
97 AnnotationProcessingOptions options = new AnnotationProcessingOptionsImpl();
98
99 for ( DefaultConstraintMapping mapping : mappings ) {
100 options.merge( mapping.getAnnotationProcessingOptions() );
101 }
102
103 return options;
104 }
105
106 @Override
107 @SuppressWarnings("unchecked")
108 public <T> BeanConfiguration<T> getBeanConfiguration(Class<T> beanClass) {
109 return (BeanConfiguration<T>) configuredBeans.get( beanClass.getName() );
110 }
111
112 @Override
113 public AnnotationProcessingOptions getAnnotationProcessingOptions() {
114 return annotationProcessingOptions;
115 }
116 }
117