24
24
import java .lang .reflect .Field ;
25
25
import java .lang .reflect .Member ;
26
26
import java .lang .reflect .Method ;
27
- import java .lang .reflect .Modifier ;
28
27
import java .lang .reflect .Parameter ;
29
28
import java .lang .reflect .ParameterizedType ;
30
29
import java .lang .reflect .Type ;
37
36
import java .util .HashSet ;
38
37
import java .util .List ;
39
38
import java .util .Map ;
39
+ import java .util .Optional ;
40
40
import java .util .Set ;
41
41
import java .util .stream .Collectors ;
42
+ import java .util .stream .Stream ;
42
43
43
44
import javax .validation .GroupSequence ;
44
45
import javax .validation .Valid ;
66
67
import org .hibernate .validator .internal .properties .Callable ;
67
68
import org .hibernate .validator .internal .properties .Constrainable ;
68
69
import org .hibernate .validator .internal .properties .Property ;
70
+ import org .hibernate .validator .internal .properties .javabean .JavaBean ;
69
71
import org .hibernate .validator .internal .properties .javabean .JavaBeanExecutable ;
70
72
import org .hibernate .validator .internal .properties .javabean .JavaBeanField ;
71
73
import org .hibernate .validator .internal .util .CollectionHelper ;
74
76
import org .hibernate .validator .internal .util .annotation .ConstraintAnnotationDescriptor ;
75
77
import org .hibernate .validator .internal .util .logging .Log ;
76
78
import 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 ;
80
81
import org .hibernate .validator .internal .util .privilegedactions .GetMethods ;
81
82
import org .hibernate .validator .internal .util .privilegedactions .NewInstance ;
82
- import org .hibernate .validator .properties .GetterPropertyMatcher ;
83
+ import org .hibernate .validator .spi . properties .GetterPropertyMatcher ;
83
84
import org .hibernate .validator .spi .group .DefaultGroupSequenceProvider ;
84
85
85
86
/**
@@ -138,23 +139,33 @@ public <T> BeanConfiguration<T> getBeanConfiguration(Class<T> beanClass) {
138
139
* @return Retrieves constraint related meta data from the annotations of the given type.
139
140
*/
140
141
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 );
144
143
144
+ Stream <ConstrainedElement > classLevelStream ;
145
145
//TODO GM: currently class level constraints are represented by a PropertyMetaData. This
146
146
//works but seems somewhat unnatural
147
147
Set <MetaConstraint <?>> classLevelConstraints = getClassLevelConstraints ( beanClass );
148
148
if ( !classLevelConstraints .isEmpty () ) {
149
- ConstrainedType classLevelMetaData =
149
+ classLevelStream = Stream . of (
150
150
new ConstrainedType (
151
151
ConfigurationSource .ANNOTATION ,
152
152
beanClass ,
153
153
classLevelConstraints
154
- );
155
- constrainedElements .add ( classLevelMetaData );
154
+ )
155
+ );
156
+ }
157
+ else {
158
+ classLevelStream = Stream .empty ();
156
159
}
157
160
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
+
158
169
return new BeanConfiguration <>(
159
170
ConfigurationSource .ANNOTATION ,
160
171
beanClass ,
@@ -164,6 +175,19 @@ private <T> BeanConfiguration<T> retrieveBeanConfiguration(Class<T> beanClass) {
164
175
);
165
176
}
166
177
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
+
167
191
private List <Class <?>> getDefaultGroupSequence (Class <?> beanClass ) {
168
192
GroupSequence groupSequenceAnnotation = beanClass .getAnnotation ( GroupSequence .class );
169
193
return groupSequenceAnnotation != null ? Arrays .asList ( groupSequenceAnnotation .value () ) : null ;
@@ -218,25 +242,8 @@ private Set<MetaConstraint<?>> getClassLevelConstraints(Class<?> clazz) {
218
242
return classLevelConstraints ;
219
243
}
220
244
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 ) ) );
240
247
Set <MetaConstraint <?>> constraints = convertToMetaConstraints (
241
248
findConstraints ( field , ElementType .FIELD , property ),
242
249
property
@@ -269,44 +276,17 @@ private Set<MetaConstraint<?>> convertToMetaConstraints(List<ConstraintDescripto
269
276
return constraints ;
270
277
}
271
278
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
-
300
279
/**
301
280
* Finds all constraint annotations defined for the given method or constructor.
302
281
*
303
- * @param executable The executable element to check for constraints annotations.
282
+ * @param callable The executable element to check for constraints annotations.
304
283
*
305
284
* @return A meta data object describing the constraints specified for the
306
- * given element.
285
+ * given element.
307
286
*/
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
+
310
290
List <ConstrainedParameter > parameterConstraints = getParameterMetaData ( executable , callable );
311
291
312
292
Map <ConstraintType , List <ConstraintDescriptorImpl <?>>> executableConstraints = findConstraints (
@@ -834,7 +814,7 @@ private TypeArgumentExecutableParameterLocation(Executable executable, int index
834
814
835
815
@ Override
836
816
public ConstraintLocation toConstraintLocation (GetterPropertyMatcher getterPropertyMatcher ) {
837
- return ConstraintLocation .forParameter ( JavaBeanExecutable . of ( getterPropertyMatcher , executable ), index );
817
+ return ConstraintLocation .forParameter ( JavaBean . toJavaBeanExecutable ( getterPropertyMatcher , executable ), index );
838
818
}
839
819
}
840
820
@@ -860,7 +840,7 @@ private TypeArgumentReturnValueLocation(Executable executable) {
860
840
861
841
@ Override
862
842
public ConstraintLocation toConstraintLocation (GetterPropertyMatcher getterPropertyMatcher ) {
863
- return ConstraintLocation .forReturnValue ( JavaBeanExecutable . of ( getterPropertyMatcher , executable ) );
843
+ return ConstraintLocation .forReturnValue ( JavaBean . toJavaBeanExecutable ( getterPropertyMatcher , executable ) );
864
844
}
865
845
}
866
846
0 commit comments