1 /*
2  * Hibernate Validator, declare and validate application constraints
3  *
4  * License: Apache License, Version 2.0
5  * See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.
6  */

7 package org.hibernate.validator.internal.cfg.context;
8
9 import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet;
10 import static org.hibernate.validator.internal.util.logging.Messages.MESSAGES;
11
12 import java.lang.annotation.Annotation;
13 import java.lang.invoke.MethodHandles;
14 import java.util.Set;
15
16 import javax.validation.Constraint;
17
18 import org.hibernate.validator.cfg.ConstraintMapping;
19 import org.hibernate.validator.cfg.context.ConstraintDefinitionContext;
20 import org.hibernate.validator.cfg.context.TypeConstraintMappingContext;
21 import org.hibernate.validator.internal.engine.ConstraintCreationContext;
22 import org.hibernate.validator.internal.engine.constraintdefinition.ConstraintDefinitionContribution;
23 import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl;
24 import org.hibernate.validator.internal.metadata.raw.BeanConfiguration;
25 import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper;
26 import org.hibernate.validator.internal.util.Contracts;
27 import org.hibernate.validator.internal.util.logging.Log;
28 import org.hibernate.validator.internal.util.logging.LoggerFactory;
29
30 /**
31  * Default implementation of {@link ConstraintMapping}.
32  *
33  * @author Hardy Ferentschik
34  * @author Gunnar Morling
35  * @author Kevin Pollet &lt;kevin.pollet@serli.com&gt; (C) 2011 SERLI
36  */

37 public class DefaultConstraintMapping implements ConstraintMapping {
38
39     private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() );
40
41     private final JavaBeanHelper javaBeanHelper;
42     private final AnnotationProcessingOptionsImpl annotationProcessingOptions;
43     private final Set<Class<?>> configuredTypes;
44     private final Set<TypeConstraintMappingContextImpl<?>> typeContexts;
45     private final Set<Class<?>> definedConstraints;
46     private final Set<ConstraintDefinitionContextImpl<?>> constraintContexts;
47
48     public DefaultConstraintMapping(JavaBeanHelper javaBeanHelper) {
49         this.javaBeanHelper = javaBeanHelper;
50         this.annotationProcessingOptions = new AnnotationProcessingOptionsImpl();
51         this.configuredTypes = newHashSet();
52         this.typeContexts = newHashSet();
53         this.definedConstraints = newHashSet();
54         this.constraintContexts = newHashSet();
55     }
56
57     @Override
58     public final <C> TypeConstraintMappingContext<C> type(Class<C> type) {
59         Contracts.assertNotNull( type, MESSAGES.beanTypeMustNotBeNull() );
60
61         if ( configuredTypes.contains( type ) ) {
62             throw LOG.getBeanClassHasAlreadyBeConfiguredViaProgrammaticApiException( type );
63         }
64
65         TypeConstraintMappingContextImpl<C> typeContext = new TypeConstraintMappingContextImpl<>( javaBeanHelper, this, type );
66         typeContexts.add( typeContext );
67         configuredTypes.add( type );
68
69         return typeContext;
70     }
71
72     public final AnnotationProcessingOptionsImpl getAnnotationProcessingOptions() {
73         return annotationProcessingOptions;
74     }
75
76     public Set<Class<?>> getConfiguredTypes() {
77         return configuredTypes;
78     }
79
80     /**
81      * Returns all bean configurations configured through this constraint mapping.
82      *
83      * @param constraintCreationContext the constraint creation context
84      *
85      * @return a set of {@link BeanConfiguration}s with an element for each type configured through this mapping
86      */

87     public Set<BeanConfiguration<?>> getBeanConfigurations(ConstraintCreationContext constraintCreationContext) {
88         Set<BeanConfiguration<?>> configurations = newHashSet();
89
90         for ( TypeConstraintMappingContextImpl<?> typeContext : typeContexts ) {
91             configurations.add( typeContext.build( constraintCreationContext ) );
92         }
93
94         return configurations;
95     }
96
97     @Override
98     public <A extends Annotation> ConstraintDefinitionContext<A> constraintDefinition(Class<A> annotationClass) {
99         Contracts.assertNotNull( annotationClass, MESSAGES.annotationTypeMustNotBeNull() );
100         Contracts.assertTrue( annotationClass.isAnnotationPresent( Constraint.class ),
101                 MESSAGES.annotationTypeMustBeAnnotatedWithConstraint() );
102
103         if ( definedConstraints.contains( annotationClass ) ) {
104             // Fail fast for easy-to-detect definition conflicts; other conflicts are handled in ValidatorFactoryImpl
105             throw LOG.getConstraintHasAlreadyBeenConfiguredViaProgrammaticApiException( annotationClass );
106         }
107
108         ConstraintDefinitionContextImpl<A> constraintContext = new ConstraintDefinitionContextImpl<>( this, annotationClass );
109         constraintContexts.add( constraintContext );
110         definedConstraints.add( annotationClass );
111
112         return constraintContext;
113     }
114
115     public Set<ConstraintDefinitionContribution<?>> getConstraintDefinitionContributions() {
116         Set<ConstraintDefinitionContribution<?>> contributions = newHashSet();
117
118         for ( ConstraintDefinitionContextImpl<?> constraintContext : constraintContexts ) {
119             contributions.add( constraintContext.build() );
120         }
121
122         return contributions;
123     }
124 }
125