Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit bb2973c

Browse files
HV-2127 Use nodes instead of paths to track processed beans
Signed-off-by: marko-bekhta <marko.prykladna@gmail.com>
1 parent 4541353 commit bb2973c

File tree

3 files changed

+51
-42
lines changed

3 files changed

+51
-42
lines changed

‎engine/src/main/java/org/hibernate/validator/internal/engine/path/NodeImpl.java

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,16 @@ public boolean equals(Object obj) {
502502
return false;
503503
}
504504
NodeImpl other = (NodeImpl) obj;
505+
return samePath( other );
506+
}
507+
508+
boolean sameNode(NodeImpl other) {
509+
if ( this == other ) {
510+
return true;
511+
}
512+
if ( other == null ) {
513+
return false;
514+
}
505515
if ( hashCode != -1 && other.hashCode != -1 && hashCode != other.hashCode ) {
506516
return false;
507517
}
@@ -570,7 +580,24 @@ else if ( !Arrays.equals( parameterTypes, other.parameterTypes ) ) {
570580
return true;
571581
}
572582

573-
boolean isRootPath() {
583+
boolean samePath(NodeImpl other) {
584+
if ( this.size != other.size ) {
585+
return false;
586+
}
587+
NodeImpl curr = this;
588+
NodeImpl otherCurr = other;
589+
while ( curr != null && otherCurr != null ) {
590+
if ( !curr.sameNode( otherCurr ) ) {
591+
return false;
592+
}
593+
otherCurr = otherCurr.parent;
594+
curr = curr.parent;
595+
}
596+
597+
return curr == null && otherCurr == null;
598+
}
599+
600+
public boolean isRootPath() {
574601
return parent == null && name == null;
575602
}
576603

@@ -615,7 +642,7 @@ boolean isSubPathOf(NodeImpl other) {
615642
return curr.isRootPath();
616643
}
617644

618-
boolean isSubPathOrContains(NodeImpl other) {
645+
publicboolean isSubPathOrContains(NodeImpl other) {
619646
NodeImpl curr;
620647
NodeImpl otherCurr;
621648
if ( this.size > other.size ) {
@@ -644,23 +671,6 @@ boolean isSubPathOrContains(NodeImpl other) {
644671
return curr.isRootPath() && otherCurr.isRootPath();
645672
}
646673

647-
boolean samePath(NodeImpl other) {
648-
if ( this.size != other.size ) {
649-
return false;
650-
}
651-
NodeImpl curr = this;
652-
NodeImpl otherCurr = other;
653-
while ( curr != null && otherCurr != null ) {
654-
if ( !curr.equals( otherCurr ) ) {
655-
return false;
656-
}
657-
otherCurr = otherCurr.parent;
658-
curr = curr.parent;
659-
}
660-
661-
return curr == null && otherCurr == null;
662-
}
663-
664674
protected static class NodeIterator implements Iterator<Path.Node> {
665675
private final NodeImpl[] array;
666676
private int index;

‎engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/AbstractValidationContext.java

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager;
2626
import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintViolationCreationContext;
2727
import org.hibernate.validator.internal.engine.path.ModifiablePath;
28+
import org.hibernate.validator.internal.engine.path.NodeImpl;
2829
import org.hibernate.validator.internal.engine.valuecontext.ValueContext;
2930
import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData;
3031
import org.hibernate.validator.internal.metadata.core.MetaConstraint;
@@ -109,10 +110,10 @@ abstract class AbstractValidationContext<T> implements BaseBeanValidationContext
109110
private Set<BeanGroupProcessedUnit> processedGroupUnits;
110111

111112
/**
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.
113114
*/
114115
@Lazy
115-
private Map<Object, Set<ModifiablePath>> processedPathsPerBean;
116+
private Map<Object, Set<NodeImpl>> processedPathsPerBean;
116117

117118
/**
118119
* Contains all failing constraints so far.
@@ -200,11 +201,10 @@ public boolean isBeanAlreadyValidated(Object value, Class<?> group, ModifiablePa
200201
return false;
201202
}
202203

203-
boolean alreadyValidated;
204-
alreadyValidated = isAlreadyValidatedForCurrentGroup( value, group );
204+
boolean alreadyValidated = isAlreadyValidatedForCurrentGroup( value, group );
205205

206206
if ( alreadyValidated ) {
207-
alreadyValidated = isAlreadyValidatedForPath( value, path );
207+
alreadyValidated = isAlreadyValidatedForPath( value, path.getLeafNode() );
208208
}
209209

210210
return alreadyValidated;
@@ -270,7 +270,7 @@ protected abstract ConstraintViolation<T> createConstraintViolation(
270270
ConstraintViolationCreationContext constraintViolationCreationContext);
271271

272272
@Override
273-
public boolean hasMetaConstraintBeenProcessed(Object bean, Path path, MetaConstraint<?> metaConstraint) {
273+
public boolean hasMetaConstraintBeenProcessed(Object bean, ModifiablePath path, MetaConstraint<?> metaConstraint) {
274274
// this is only useful if the constraint is defined for more than 1 group as in the case it's only
275275
// defined for one group, there is no chance it's going to be called twice.
276276
if ( metaConstraint.isDefinedForOneGroupOnly() ) {
@@ -281,7 +281,7 @@ public boolean hasMetaConstraintBeenProcessed(Object bean, Path path, MetaConstr
281281
}
282282

283283
@Override
284-
public void markConstraintProcessed(Object bean, Path path, MetaConstraint<?> metaConstraint) {
284+
public void markConstraintProcessed(Object bean, ModifiablePath path, MetaConstraint<?> metaConstraint) {
285285
// this is only useful if the constraint is defined for more than 1 group as in the case it's only
286286
// defined for one group, there is no chance it's going to be called twice.
287287
if ( metaConstraint.isDefinedForOneGroupOnly() ) {
@@ -340,8 +340,8 @@ private String interpolate(
340340
}
341341
}
342342

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 );
345345
if ( pathSet == null ) {
346346
return false;
347347
}
@@ -354,7 +354,7 @@ private boolean isAlreadyValidatedForPath(Object value, ModifiablePath path) {
354354
// it means that the new path we are testing cannot be a root path; also since we are cascading into inner
355355
// objects, i.e. going further from the object tree root, it means that the new path cannot be shorter than
356356
// the ones we've already encountered.
357-
for ( ModifiablePath p : pathSet ) {
357+
for ( NodeImpl p : pathSet ) {
358358
if ( p.isSubPathOrContains( path ) ) {
359359
return true;
360360
}
@@ -367,16 +367,16 @@ private boolean isAlreadyValidatedForCurrentGroup(Object value, Class<?> group)
367367
}
368368

369369
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();
372371

373-
Set<ModifiablePath> processedPaths = processedPathsPerBean.get( bean );
372+
Set<NodeImpl> processedPaths = processedPathsPerBean.get( bean );
374373
if ( processedPaths == null ) {
375374
processedPaths = new HashSet<>();
376375
processedPathsPerBean.put( bean, processedPaths );
377376
}
378377

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() );
380380
}
381381

382382
private void markCurrentBeanAsProcessedForCurrentGroup(Object bean, Class<?> group) {
@@ -397,7 +397,7 @@ private Set<BeanGroupProcessedUnit> getInitializedProcessedGroupUnits() {
397397
return processedGroupUnits;
398398
}
399399

400-
private Map<Object, Set<ModifiablePath>> getInitializedProcessedPathsPerBean() {
400+
private Map<Object, Set<NodeImpl>> getInitializedProcessedPathsPerBean() {
401401
if ( processedPathsPerBean == null ) {
402402
processedPathsPerBean = new IdentityHashMap<>();
403403
}
@@ -415,13 +415,13 @@ private static final class BeanPathMetaConstraintProcessedUnit {
415415

416416
// these fields are final but we don't mark them as final as an optimization
417417
private Object bean;
418-
private Pathpath;
418+
private NodeImplpathLeaf;
419419
private MetaConstraint<?> metaConstraint;
420420
private int hashCode;
421421

422-
BeanPathMetaConstraintProcessedUnit(Object bean, Path path, MetaConstraint<?> metaConstraint) {
422+
BeanPathMetaConstraintProcessedUnit(Object bean, ModifiablePath path, MetaConstraint<?> metaConstraint) {
423423
this.bean = bean;
424-
this.path = path;
424+
this.pathLeaf = path.getLeafNode(); // because the leaf represent the entire path.
425425
this.metaConstraint = metaConstraint;
426426
this.hashCode = createHashCode();
427427
}
@@ -442,7 +442,7 @@ public boolean equals(Object o) {
442442
if ( metaConstraint != that.metaConstraint ) {
443443
return false;
444444
}
445-
if ( !path.equals( that.path ) ) {
445+
if ( !pathLeaf.equals( that.pathLeaf ) ) {
446446
return false;
447447
}
448448

@@ -456,7 +456,7 @@ public int hashCode() {
456456

457457
private int createHashCode() {
458458
int result = System.identityHashCode( bean );
459-
result = 31 * result + path.hashCode();
459+
result = 31 * result + pathLeaf.hashCode();
460460
result = 31 * result + System.identityHashCode( metaConstraint );
461461
return result;
462462
}

‎engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/BaseBeanValidationContext.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
*/
55
package org.hibernate.validator.internal.engine.validationcontext;
66

7-
import jakarta.validation.Path;
87
import jakarta.validation.TraversableResolver;
98
import jakarta.validation.Validator;
109

@@ -39,9 +38,9 @@ public interface BaseBeanValidationContext<T> extends ValidationContext<T> {
3938

4039
void markCurrentBeanAsProcessed(ValueContext<?, ?> valueContext);
4140

42-
boolean hasMetaConstraintBeenProcessed(Object bean, Path path, MetaConstraint<?> metaConstraint);
41+
boolean hasMetaConstraintBeenProcessed(Object bean, ModifiablePath path, MetaConstraint<?> metaConstraint);
4342

44-
void markConstraintProcessed(Object bean, Path path, MetaConstraint<?> metaConstraint);
43+
void markConstraintProcessed(Object bean, ModifiablePath path, MetaConstraint<?> metaConstraint);
4544

4645
/**
4746
* @return {@code true} if current validation context can and should process passed meta constraint. Is used in

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /