18
18
import org .hibernate .validator .internal .metadata .aggregated .CascadingMetaData ;
19
19
import org .hibernate .validator .internal .metadata .aggregated .ContainerCascadingMetaData ;
20
20
import org .hibernate .validator .internal .metadata .aggregated .PotentiallyContainerCascadingMetaData ;
21
+ import org .hibernate .validator .internal .metadata .aggregated .ReturnValueMetaData ;
22
+ import org .hibernate .validator .internal .metadata .aggregated .ValidatableParametersMetaData ;
21
23
import org .hibernate .validator .internal .metadata .facets .Cascadable ;
22
24
import org .hibernate .validator .internal .properties .Signature ;
23
25
import org .hibernate .validator .internal .util .CollectionHelper ;
@@ -26,8 +28,11 @@ public class PredefinedScopeProcessedBeansTrackingStrategy implements ProcessedB
26
28
27
29
private final Map <Class <?>, Boolean > trackingEnabledForBeans ;
28
30
31
+ // TODO: signature is just name and parameters so that can clash between different beans.
32
+ // with that.. do we even need to track it per signature or since
33
+ // we already built the `trackingEnabledForBeans` we can just "inspect" the cascadable as we go
34
+ // and check against this `trackingEnabledForBeans` to see if tracking is required ?
29
35
private final Map <Signature , Boolean > trackingEnabledForReturnValues ;
30
-
31
36
private final Map <Signature , Boolean > trackingEnabledForParameters ;
32
37
33
38
public PredefinedScopeProcessedBeansTrackingStrategy (Map <Class <?>, BeanMetaData <?>> rawBeanMetaDataMap ) {
@@ -198,92 +203,94 @@ private <T> Set<Class<?>> getDirectCascadedBeanClasses(Class<T> beanClass) {
198
203
}
199
204
200
205
for ( Cascadable cascadable : beanMetaData .getCascadables () ) {
201
- final CascadingMetaData cascadingMetaData = cascadable .getCascadingMetaData ();
202
- if ( cascadingMetaData .isContainer () ) {
203
- final ContainerCascadingMetaData containerCascadingMetaData = cascadingMetaData .as ( ContainerCascadingMetaData .class );
204
- processContainerCascadingMetaData ( containerCascadingMetaData , directCascadedBeanClasses );
205
- }
206
- else if ( cascadingMetaData instanceof PotentiallyContainerCascadingMetaData potentiallyContainerCascadingMetaData ) {
207
- // if it's a potentially container cascading one, we are "in trouble" as thing can be "almost anything".
208
- // TODO: would it be enough to just take the type as defined ?
209
- // directCascadedBeanClasses.add( (Class<?>) cascadable.getCascadableType() );
210
- //
211
- // TODO: or be much more cautious and just assume that it can be "anything":
212
- directCascadedBeanClasses .add ( Object .class );
213
- }
214
- else {
215
- // TODO: For now, assume non-container Cascadables are always beans. Truee???
216
- directCascadedBeanClasses .add ( typeToClassToProcess ( cascadable .getCascadableType () ) );
217
- }
206
+ processSingleCascadable ( cascadable , directCascadedBeanClasses );
218
207
}
219
208
}
220
209
return directCascadedBeanClasses ;
221
210
}
222
211
223
- private static void processContainerCascadingMetaData (ContainerCascadingMetaData metaData , Set <Class <?>> directCascadedBeanClasses ) {
224
- if ( metaData .isCascading () ) {
225
- if ( metaData .getDeclaredTypeParameterIndex () != null ) {
226
- if ( metaData .getEnclosingType () instanceof ParameterizedType parameterizedType ) {
227
- Type typeArgument = parameterizedType .getActualTypeArguments ()[metaData .getDeclaredTypeParameterIndex ()];
228
- if ( typeArgument instanceof Class <?> typeArgumentClass ) {
229
- directCascadedBeanClasses .add ( typeArgumentClass );
230
- }
231
- else if ( typeArgument instanceof TypeVariable <?> typeVariable ) {
232
- for ( Type bound : typeVariable .getBounds () ) {
233
- directCascadedBeanClasses .add ( typeToClassToProcess ( bound ) );
234
- }
212
+ private boolean register (Class <?> beanClass , boolean isBeanTrackingEnabled ) {
213
+ if ( classToBeanTrackingEnabled .put ( beanClass , isBeanTrackingEnabled ) != null ) {
214
+ throw new IllegalStateException ( beanClass .getName () + " registered more than once." );
215
+ }
216
+ return isBeanTrackingEnabled ;
217
+ }
218
+ }
219
+
220
+ private static void processSingleCascadable (Cascadable cascadable , Set <Class <?>> directCascadedBeanClasses ) {
221
+ CascadingMetaData cascadingMetaData = cascadable .getCascadingMetaData ();
222
+ if ( cascadingMetaData .isContainer () ) {
223
+ final ContainerCascadingMetaData containerCascadingMetaData = cascadingMetaData .as ( ContainerCascadingMetaData .class );
224
+ processContainerCascadingMetaData ( containerCascadingMetaData , directCascadedBeanClasses );
225
+ }
226
+ else if ( cascadingMetaData instanceof PotentiallyContainerCascadingMetaData potentiallyContainerCascadingMetaData ) {
227
+ // if it's a potentially container cascading one, we are "in trouble" as thing can be "almost anything".
228
+ // TODO: would it be enough to just take the type as defined ?
229
+ // directCascadedBeanClasses.add( (Class<?>) cascadable.getCascadableType() );
230
+ //
231
+ // TODO: or be much more cautious and just assume that it can be "anything":
232
+ directCascadedBeanClasses .add ( Object .class );
233
+ }
234
+ else {
235
+ // TODO: For now, assume non-container Cascadables are always beans. Truee???
236
+ directCascadedBeanClasses .add ( typeToClassToProcess ( cascadable .getCascadableType () ) );
237
+ }
238
+ }
239
+
240
+ private static void processContainerCascadingMetaData (ContainerCascadingMetaData metaData , Set <Class <?>> directCascadedBeanClasses ) {
241
+ if ( metaData .isCascading () ) {
242
+ if ( metaData .getDeclaredTypeParameterIndex () != null ) {
243
+ if ( metaData .getEnclosingType () instanceof ParameterizedType parameterizedType ) {
244
+ Type typeArgument = parameterizedType .getActualTypeArguments ()[metaData .getDeclaredTypeParameterIndex ()];
245
+ if ( typeArgument instanceof Class <?> typeArgumentClass ) {
246
+ directCascadedBeanClasses .add ( typeArgumentClass );
247
+ }
248
+ else if ( typeArgument instanceof TypeVariable <?> typeVariable ) {
249
+ for ( Type bound : typeVariable .getBounds () ) {
250
+ directCascadedBeanClasses .add ( typeToClassToProcess ( bound ) );
235
251
}
236
- else if ( typeArgument instanceof WildcardType wildcard ) {
237
- for ( Type bound : wildcard .getUpperBounds () ) {
238
- directCascadedBeanClasses .add ( typeToClassToProcess ( bound ) );
239
- }
240
- if ( wildcard .getLowerBounds ().length != 0 ) {
241
- // if it's a lower bound ? super smth ... it doesn't matter anymore since it can contain anything so go with object ?
242
- directCascadedBeanClasses .add ( Object .class );
243
- }
252
+ }
253
+ else if ( typeArgument instanceof WildcardType wildcard ) {
254
+ for ( Type bound : wildcard .getUpperBounds () ) {
255
+ directCascadedBeanClasses .add ( typeToClassToProcess ( bound ) );
244
256
}
245
- else {
246
- // TODO: instead of failing, add an Object.class and assume it can be anything ?
247
- throw new UnsupportedOperationException ( typeArgument . getClass (). getSimpleName () + " type argument values are not supported." );
257
+ if ( wildcard . getLowerBounds (). length != 0 ) {
258
+ // if it's a lower bound ? super smth ... it doesn't matter anymore since it can contain anything so go with object ?
259
+ directCascadedBeanClasses . add ( Object . class );
248
260
}
249
261
}
250
- }
251
- else {
252
- // If we do not have the type arguments then we can go though the value extractors,
253
- // as they are required to define the `@ExtractedValue(type = ???)` ...
254
- // this way we should get the type we want:
255
- for ( ValueExtractorDescriptor valueExtractorCandidate : metaData .getValueExtractorCandidates () ) {
256
- valueExtractorCandidate .getExtractedType ().ifPresent ( directCascadedBeanClasses ::add );
262
+ else {
263
+ // TODO: instead of failing, add an Object.class and assume it can be anything ?
264
+ throw new UnsupportedOperationException ( typeArgument .getClass ().getSimpleName () + " type argument values are not supported." );
257
265
}
258
266
}
259
267
}
260
-
261
- if ( metaData .getEnclosingType () instanceof ParameterizedType parameterizedType ) {
262
- for ( ContainerCascadingMetaData sub : metaData .getContainerElementTypesCascadingMetaData () ) {
263
- processContainerCascadingMetaData ( sub , directCascadedBeanClasses );
268
+ else {
269
+ // If we do not have the type arguments then we can go though the value extractors,
270
+ // as they are required to define the `@ExtractedValue(type = ???)` ...
271
+ // this way we should get the type we want:
272
+ for ( ValueExtractorDescriptor valueExtractorCandidate : metaData .getValueExtractorCandidates () ) {
273
+ valueExtractorCandidate .getExtractedType ().ifPresent ( directCascadedBeanClasses ::add );
264
274
}
265
275
}
266
276
}
267
277
268
- private static Class <?> typeToClassToProcess (Type type ) {
269
- if ( type instanceof Class <?> cascadableClass ) {
270
- return cascadableClass ;
271
- }
272
- else if ( type instanceof ParameterizedType parameterizedType ) {
273
- return typeToClassToProcess ( parameterizedType .getRawType () );
274
- }
275
- else {
276
- // TODO: instead of failing, add an Object.class and assume it can be anything ?
277
- // return Object.class;
278
- throw new UnsupportedOperationException ( type .getClass ().getSimpleName () + " type values are not supported." );
279
- }
278
+ for ( ContainerCascadingMetaData sub : metaData .getContainerElementTypesCascadingMetaData () ) {
279
+ processContainerCascadingMetaData ( sub , directCascadedBeanClasses );
280
280
}
281
+ }
281
282
282
- private boolean register (Class <?> beanClass , boolean isBeanTrackingEnabled ) {
283
- if ( classToBeanTrackingEnabled .put ( beanClass , isBeanTrackingEnabled ) != null ) {
284
- throw new IllegalStateException ( beanClass .getName () + " registered more than once." );
285
- }
286
- return isBeanTrackingEnabled ;
283
+ private static Class <?> typeToClassToProcess (Type type ) {
284
+ if ( type instanceof Class <?> cascadableClass ) {
285
+ return cascadableClass ;
286
+ }
287
+ else if ( type instanceof ParameterizedType parameterizedType ) {
288
+ return typeToClassToProcess ( parameterizedType .getRawType () );
289
+ }
290
+ else {
291
+ // TODO: instead of failing, add an Object.class and assume it can be anything ?
292
+ // return Object.class;
293
+ throw new UnsupportedOperationException ( type .getClass ().getSimpleName () + " type values are not supported." );
287
294
}
288
295
}
289
296
@@ -305,6 +312,25 @@ public boolean isEnabledForReturnValue(Signature signature, boolean hasCascadabl
305
312
return trackingEnabledForReturnValues .getOrDefault ( signature , true );
306
313
}
307
314
315
+ @ Override
316
+ public boolean isEnabledForReturnValue (ReturnValueMetaData returnValueMetaData ) {
317
+ if ( !returnValueMetaData .isCascading () ) {
318
+ return false ;
319
+ }
320
+
321
+ Set <Class <?>> directCascadedBeanClasses = new HashSet <>();
322
+ for ( Cascadable cascadable : returnValueMetaData .getCascadables () ) {
323
+ processSingleCascadable ( cascadable , directCascadedBeanClasses );
324
+ }
325
+ for ( Class <?> directCascadedBeanClass : directCascadedBeanClasses ) {
326
+ if ( trackingEnabledForBeans .get ( directCascadedBeanClass ) ) {
327
+ return true ;
328
+ }
329
+ }
330
+
331
+ return false ;
332
+ }
333
+
308
334
@ Override
309
335
public boolean isEnabledForParameters (Signature signature , boolean hasCascadables ) {
310
336
if ( !hasCascadables ) {
@@ -314,6 +340,25 @@ public boolean isEnabledForParameters(Signature signature, boolean hasCascadable
314
340
return trackingEnabledForParameters .getOrDefault ( signature , true );
315
341
}
316
342
343
+ @ Override
344
+ public boolean isEnabledForParameters (ValidatableParametersMetaData parametersMetaData ) {
345
+ if ( !parametersMetaData .hasCascadables () ) {
346
+ return false ;
347
+ }
348
+
349
+ Set <Class <?>> directCascadedBeanClasses = new HashSet <>();
350
+ for ( Cascadable cascadable : parametersMetaData .getCascadables () ) {
351
+ processSingleCascadable ( cascadable , directCascadedBeanClasses );
352
+ }
353
+ for ( Class <?> directCascadedBeanClass : directCascadedBeanClasses ) {
354
+ if ( trackingEnabledForBeans .get ( directCascadedBeanClass ) ) {
355
+ return true ;
356
+ }
357
+ }
358
+
359
+ return false ;
360
+ }
361
+
317
362
@ Override
318
363
public void clear () {
319
364
trackingEnabledForBeans .clear ();
0 commit comments