25
25
import org .hibernate .validator .internal .engine .constraintvalidation .ConstraintValidatorManager ;
26
26
import org .hibernate .validator .internal .engine .constraintvalidation .ConstraintViolationCreationContext ;
27
27
import org .hibernate .validator .internal .engine .path .ModifiablePath ;
28
+ import org .hibernate .validator .internal .engine .path .NodeImpl ;
28
29
import org .hibernate .validator .internal .engine .valuecontext .ValueContext ;
29
30
import org .hibernate .validator .internal .metadata .aggregated .BeanMetaData ;
30
31
import org .hibernate .validator .internal .metadata .core .MetaConstraint ;
@@ -109,10 +110,10 @@ abstract class AbstractValidationContext<T> implements BaseBeanValidationContext
109
110
private Set <BeanGroupProcessedUnit > processedGroupUnits ;
110
111
111
112
/**
112
- * Maps an object to a list of paths in which it has been validated. The objects are the bean instances.
113
+ * Maps an object to a list of paths (represented by leaf nodes) in which it has been validated. The objects are the bean instances.
113
114
*/
114
115
@ Lazy
115
- private Map <Object , Set <ModifiablePath >> processedPathsPerBean ;
116
+ private Map <Object , Set <NodeImpl >> processedPathsPerBean ;
116
117
117
118
/**
118
119
* Contains all failing constraints so far.
@@ -200,11 +201,10 @@ public boolean isBeanAlreadyValidated(Object value, Class<?> group, ModifiablePa
200
201
return false ;
201
202
}
202
203
203
- boolean alreadyValidated ;
204
- alreadyValidated = isAlreadyValidatedForCurrentGroup ( value , group );
204
+ boolean alreadyValidated = isAlreadyValidatedForCurrentGroup ( value , group );
205
205
206
206
if ( alreadyValidated ) {
207
- alreadyValidated = isAlreadyValidatedForPath ( value , path );
207
+ alreadyValidated = isAlreadyValidatedForPath ( value , path . getLeafNode () );
208
208
}
209
209
210
210
return alreadyValidated ;
@@ -270,7 +270,7 @@ protected abstract ConstraintViolation<T> createConstraintViolation(
270
270
ConstraintViolationCreationContext constraintViolationCreationContext );
271
271
272
272
@ Override
273
- public boolean hasMetaConstraintBeenProcessed (Object bean , Path path , MetaConstraint <?> metaConstraint ) {
273
+ public boolean hasMetaConstraintBeenProcessed (Object bean , ModifiablePath path , MetaConstraint <?> metaConstraint ) {
274
274
// this is only useful if the constraint is defined for more than 1 group as in the case it's only
275
275
// defined for one group, there is no chance it's going to be called twice.
276
276
if ( metaConstraint .isDefinedForOneGroupOnly () ) {
@@ -281,7 +281,7 @@ public boolean hasMetaConstraintBeenProcessed(Object bean, Path path, MetaConstr
281
281
}
282
282
283
283
@ Override
284
- public void markConstraintProcessed (Object bean , Path path , MetaConstraint <?> metaConstraint ) {
284
+ public void markConstraintProcessed (Object bean , ModifiablePath path , MetaConstraint <?> metaConstraint ) {
285
285
// this is only useful if the constraint is defined for more than 1 group as in the case it's only
286
286
// defined for one group, there is no chance it's going to be called twice.
287
287
if ( metaConstraint .isDefinedForOneGroupOnly () ) {
@@ -340,8 +340,8 @@ private String interpolate(
340
340
}
341
341
}
342
342
343
- private boolean isAlreadyValidatedForPath (Object value , ModifiablePath path ) {
344
- Set <ModifiablePath > pathSet = getInitializedProcessedPathsPerBean ().get ( value );
343
+ private boolean isAlreadyValidatedForPath (Object value , NodeImpl path ) {
344
+ Set <NodeImpl > pathSet = getInitializedProcessedPathsPerBean ().get ( value );
345
345
if ( pathSet == null ) {
346
346
return false ;
347
347
}
@@ -354,7 +354,7 @@ private boolean isAlreadyValidatedForPath(Object value, ModifiablePath path) {
354
354
// it means that the new path we are testing cannot be a root path; also since we are cascading into inner
355
355
// objects, i.e. going further from the object tree root, it means that the new path cannot be shorter than
356
356
// the ones we've already encountered.
357
- for ( ModifiablePath p : pathSet ) {
357
+ for ( NodeImpl p : pathSet ) {
358
358
if ( p .isSubPathOrContains ( path ) ) {
359
359
return true ;
360
360
}
@@ -367,16 +367,16 @@ private boolean isAlreadyValidatedForCurrentGroup(Object value, Class<?> group)
367
367
}
368
368
369
369
private void markCurrentBeanAsProcessedForCurrentPath (Object bean , ModifiablePath path ) {
370
- // HV-1031 The path object is mutated as we traverse the object tree, hence copy it before saving it
371
- Map <Object , Set <ModifiablePath >> processedPathsPerBean = getInitializedProcessedPathsPerBean ();
370
+ Map <Object , Set <NodeImpl >> processedPathsPerBean = getInitializedProcessedPathsPerBean ();
372
371
373
- Set <ModifiablePath > processedPaths = processedPathsPerBean .get ( bean );
372
+ Set <NodeImpl > processedPaths = processedPathsPerBean .get ( bean );
374
373
if ( processedPaths == null ) {
375
374
processedPaths = new HashSet <>();
376
375
processedPathsPerBean .put ( bean , processedPaths );
377
376
}
378
377
379
- processedPaths .add ( ModifiablePath .createCopy ( path ) );
378
+ // HV-1031 The path object is mutated as we traverse the object tree, hence we use the node which is not (for the most part):
379
+ processedPaths .add ( path .getLeafNode () );
380
380
}
381
381
382
382
private void markCurrentBeanAsProcessedForCurrentGroup (Object bean , Class <?> group ) {
@@ -397,7 +397,7 @@ private Set<BeanGroupProcessedUnit> getInitializedProcessedGroupUnits() {
397
397
return processedGroupUnits ;
398
398
}
399
399
400
- private Map <Object , Set <ModifiablePath >> getInitializedProcessedPathsPerBean () {
400
+ private Map <Object , Set <NodeImpl >> getInitializedProcessedPathsPerBean () {
401
401
if ( processedPathsPerBean == null ) {
402
402
processedPathsPerBean = new IdentityHashMap <>();
403
403
}
@@ -415,13 +415,13 @@ private static final class BeanPathMetaConstraintProcessedUnit {
415
415
416
416
// these fields are final but we don't mark them as final as an optimization
417
417
private Object bean ;
418
- private Path path ;
418
+ private NodeImpl pathLeaf ;
419
419
private MetaConstraint <?> metaConstraint ;
420
420
private int hashCode ;
421
421
422
- BeanPathMetaConstraintProcessedUnit (Object bean , Path path , MetaConstraint <?> metaConstraint ) {
422
+ BeanPathMetaConstraintProcessedUnit (Object bean , ModifiablePath path , MetaConstraint <?> metaConstraint ) {
423
423
this .bean = bean ;
424
- this .path = path ;
424
+ this .pathLeaf = path . getLeafNode (); // because the leaf represent the entire path.
425
425
this .metaConstraint = metaConstraint ;
426
426
this .hashCode = createHashCode ();
427
427
}
@@ -442,7 +442,7 @@ public boolean equals(Object o) {
442
442
if ( metaConstraint != that .metaConstraint ) {
443
443
return false ;
444
444
}
445
- if ( !path .equals ( that .path ) ) {
445
+ if ( !pathLeaf .equals ( that .pathLeaf ) ) {
446
446
return false ;
447
447
}
448
448
@@ -456,7 +456,7 @@ public int hashCode() {
456
456
457
457
private int createHashCode () {
458
458
int result = System .identityHashCode ( bean );
459
- result = 31 * result + path .hashCode ();
459
+ result = 31 * result + pathLeaf .hashCode ();
460
460
result = 31 * result + System .identityHashCode ( metaConstraint );
461
461
return result ;
462
462
}
0 commit comments