2424import java .lang .reflect .Field ;
2525import java .lang .reflect .Member ;
2626import java .lang .reflect .Method ;
27- import java .lang .reflect .Modifier ;
2827import java .lang .reflect .Parameter ;
2928import java .lang .reflect .ParameterizedType ;
3029import java .lang .reflect .Type ;
3736import java .util .HashSet ;
3837import java .util .List ;
3938import java .util .Map ;
39+ import java .util .Optional ;
4040import java .util .Set ;
4141import java .util .stream .Collectors ;
42+ import java .util .stream .Stream ;
4243
4344import javax .validation .GroupSequence ;
4445import javax .validation .Valid ;
6667import org .hibernate .validator .internal .properties .Callable ;
6768import org .hibernate .validator .internal .properties .Constrainable ;
6869import org .hibernate .validator .internal .properties .Property ;
70+ import org .hibernate .validator .internal .properties .javabean .JavaBean ;
6971import org .hibernate .validator .internal .properties .javabean .JavaBeanExecutable ;
7072import org .hibernate .validator .internal .properties .javabean .JavaBeanField ;
7173import org .hibernate .validator .internal .util .CollectionHelper ;
7476import org .hibernate .validator .internal .util .annotation .ConstraintAnnotationDescriptor ;
7577import org .hibernate .validator .internal .util .logging .Log ;
7678import org .hibernate .validator .internal .util .logging .LoggerFactory ;
77- import org .hibernate .validator .internal .util .privilegedactions .GetDeclaredConstructors ;
78- import org .hibernate .validator .internal .util .privilegedactions .GetDeclaredFields ;
79- import org .hibernate .validator .internal .util .privilegedactions .GetDeclaredMethods ;
79+ import org .hibernate .validator .internal .util .privilegedactions .GetJavaBeanExecutableProperty ;
80+ import org .hibernate .validator .internal .util .privilegedactions .GetJavaBeanFieldProperty ;
8081import org .hibernate .validator .internal .util .privilegedactions .GetMethods ;
8182import org .hibernate .validator .internal .util .privilegedactions .NewInstance ;
82- import org .hibernate .validator .properties .GetterPropertyMatcher ;
83+ import org .hibernate .validator .spi . properties .GetterPropertyMatcher ;
8384import org .hibernate .validator .spi .group .DefaultGroupSequenceProvider ;
8485
8586/**
@@ -138,23 +139,33 @@ public <T> BeanConfiguration<T> getBeanConfiguration(Class<T> beanClass) {
138139 * @return Retrieves constraint related meta data from the annotations of the given type.
139140 */
140141 private <T > BeanConfiguration <T > retrieveBeanConfiguration (Class <T > beanClass ) {
141- Set <ConstrainedElement > constrainedElements = getFieldMetaData ( beanClass );
142- constrainedElements .addAll ( getMethodMetaData ( beanClass ) );
143- constrainedElements .addAll ( getConstructorMetaData ( beanClass ) );
142+ JavaBean javaBean = new JavaBean ( getterPropertyMatcher , beanClass );
144143
144+ Stream <ConstrainedElement > classLevelStream ;
145145 //TODO GM: currently class level constraints are represented by a PropertyMetaData. This
146146 //works but seems somewhat unnatural
147147 Set <MetaConstraint <?>> classLevelConstraints = getClassLevelConstraints ( beanClass );
148148 if ( !classLevelConstraints .isEmpty () ) {
149- ConstrainedType classLevelMetaData =
149+ classLevelStream = Stream . of (
150150 new ConstrainedType (
151151 ConfigurationSource .ANNOTATION ,
152152 beanClass ,
153153 classLevelConstraints
154- );
155- constrainedElements .add ( classLevelMetaData );
154+ )
155+ );
156+ }
157+ else {
158+ classLevelStream = Stream .empty ();
156159 }
157160
161+ Set <ConstrainedElement > constrainedElements = Stream .concat (
162+ classLevelStream ,
163+ javaBean .getAllConstrainables ()
164+ .map ( this ::toConstrainedElement )
165+ .filter ( Optional ::isPresent )
166+ .map ( Optional ::get )
167+ ).collect ( Collectors .toSet () );
168+
158169 return new BeanConfiguration <>(
159170 ConfigurationSource .ANNOTATION ,
160171 beanClass ,
@@ -164,6 +175,19 @@ private <T> BeanConfiguration<T> retrieveBeanConfiguration(Class<T> beanClass) {
164175 );
165176 }
166177
178+ private Optional <ConstrainedElement > toConstrainedElement (Constrainable constrainable ) {
179+ if ( constrainable instanceof JavaBeanField ) {
180+ if ( annotationProcessingOptions .areMemberConstraintsIgnoredFor ( constrainable ) ) {
181+ return Optional .empty ();
182+ }
183+ return Optional .of ( findPropertyMetaData ( constrainable .as ( Property .class ) ) );
184+ }
185+ else if ( constrainable instanceof JavaBeanExecutable ) {
186+ return Optional .of ( findExecutableMetaData ( constrainable .as ( Callable .class ) ) );
187+ }
188+ throw new IllegalStateException ( String .format ( "Received unknown constrainable '%s' of type %s" , constrainable .getName (), constrainable .getClass () ) );
189+ }
190+
167191 private List <Class <?>> getDefaultGroupSequence (Class <?> beanClass ) {
168192 GroupSequence groupSequenceAnnotation = beanClass .getAnnotation ( GroupSequence .class );
169193 return groupSequenceAnnotation != null ? Arrays .asList ( groupSequenceAnnotation .value () ) : null ;
@@ -218,25 +242,8 @@ private Set<MetaConstraint<?>> getClassLevelConstraints(Class<?> clazz) {
218242 return classLevelConstraints ;
219243 }
220244
221- private Set <ConstrainedElement > getFieldMetaData (Class <?> beanClass ) {
222- Set <ConstrainedElement > propertyMetaData = newHashSet ();
223-
224- for ( Field field : run ( GetDeclaredFields .action ( beanClass ) ) ) {
225- Property property = new JavaBeanField ( field );
226- // HV-172
227- if ( Modifier .isStatic ( field .getModifiers () ) ||
228- annotationProcessingOptions .areMemberConstraintsIgnoredFor ( property ) ||
229- field .isSynthetic () ) {
230-
231- continue ;
232- }
233-
234- propertyMetaData .add ( findPropertyMetaData ( field , property ) );
235- }
236- return propertyMetaData ;
237- }
238-
239- private ConstrainedProperty findPropertyMetaData (Field field , Property property ) {
245+ private ConstrainedProperty findPropertyMetaData (Property property ) {
246+ Field field = run ( GetJavaBeanFieldProperty .action ( property .as ( JavaBeanField .class ) ) );
240247 Set <MetaConstraint <?>> constraints = convertToMetaConstraints (
241248 findConstraints ( field , ElementType .FIELD , property ),
242249 property
@@ -269,44 +276,17 @@ private Set<MetaConstraint<?>> convertToMetaConstraints(List<ConstraintDescripto
269276 return constraints ;
270277 }
271278
272- private Set <ConstrainedExecutable > getConstructorMetaData (Class <?> clazz ) {
273- Executable [] declaredConstructors = run ( GetDeclaredConstructors .action ( clazz ) );
274-
275- return getMetaData ( declaredConstructors );
276- }
277-
278- private Set <ConstrainedExecutable > getMethodMetaData (Class <?> clazz ) {
279- Executable [] declaredMethods = run ( GetDeclaredMethods .action ( clazz ) );
280-
281- return getMetaData ( declaredMethods );
282- }
283-
284- private Set <ConstrainedExecutable > getMetaData (Executable [] executableElements ) {
285- Set <ConstrainedExecutable > executableMetaData = newHashSet ();
286-
287- for ( Executable executable : executableElements ) {
288- // HV-172; ignoring synthetic methods (inserted by the compiler), as they can't have any constraints
289- // anyway and possibly hide the actual method with the same signature in the built meta model
290- if ( Modifier .isStatic ( executable .getModifiers () ) || executable .isSynthetic () ) {
291- continue ;
292- }
293-
294- executableMetaData .add ( findExecutableMetaData ( executable ) );
295- }
296-
297- return executableMetaData ;
298- }
299-
300279 /**
301280 * Finds all constraint annotations defined for the given method or constructor.
302281 *
303- * @param executable The executable element to check for constraints annotations.
282+ * @param callable The executable element to check for constraints annotations.
304283 *
305284 * @return A meta data object describing the constraints specified for the
306- * given element.
285+ * given element.
307286 */
308- private ConstrainedExecutable findExecutableMetaData (Executable executable ) {
309- Callable callable = JavaBeanExecutable .of ( getterPropertyMatcher , executable );
287+ private ConstrainedExecutable findExecutableMetaData (Callable callable ) {
288+ Executable executable = run ( GetJavaBeanExecutableProperty .action ( callable .as ( JavaBeanExecutable .class ) ) );
289+
310290 List <ConstrainedParameter > parameterConstraints = getParameterMetaData ( executable , callable );
311291
312292 Map <ConstraintType , List <ConstraintDescriptorImpl <?>>> executableConstraints = findConstraints (
@@ -834,7 +814,7 @@ private TypeArgumentExecutableParameterLocation(Executable executable, int index
834814
835815 @ Override
836816 public ConstraintLocation toConstraintLocation (GetterPropertyMatcher getterPropertyMatcher ) {
837- return ConstraintLocation .forParameter ( JavaBeanExecutable . of ( getterPropertyMatcher , executable ), index );
817+ return ConstraintLocation .forParameter ( JavaBean . toJavaBeanExecutable ( getterPropertyMatcher , executable ), index );
838818 }
839819 }
840820
@@ -860,7 +840,7 @@ private TypeArgumentReturnValueLocation(Executable executable) {
860840
861841 @ Override
862842 public ConstraintLocation toConstraintLocation (GetterPropertyMatcher getterPropertyMatcher ) {
863- return ConstraintLocation .forReturnValue ( JavaBeanExecutable . of ( getterPropertyMatcher , executable ) );
843+ return ConstraintLocation .forReturnValue ( JavaBean . toJavaBeanExecutable ( getterPropertyMatcher , executable ) );
864844 }
865845 }
866846
0 commit comments