You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@bval.apache.org by ta...@apache.org on 2026/07/25 00:51:22 UTC

(bval) 01/03: BVAL-226 Remove redundant per-constraint validation de-duplication

This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/bval.git

commit d99606b257f455793f3f97f1689bd96ceb75ded4
Author: tandraschko <ta...@apache.org>
AuthorDate: Sat Jul 25 02:33:23 2026 +0200

    BVAL-226 Remove redundant per-constraint validation de-duplication
---
 .../org/apache/bval/jsr/job/ValidationJob.java     | 28 ++++++----------------
 1 file changed, 7 insertions(+), 21 deletions(-)

diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidationJob.java b/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidationJob.java
index e57cc22..3177ea6 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidationJob.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/job/ValidationJob.java
@@ -24,14 +24,12 @@ import java.lang.reflect.TypeVariable;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.IdentityHashMap;
 import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
-import java.util.TreeMap;
 import java.util.function.Consumer;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
@@ -144,16 +142,12 @@ public abstract class ValidationJob<T> {
 
         @SuppressWarnings({ "rawtypes", "unchecked" })
         private boolean validate(ConstraintD<?> constraint, Consumer<ConstraintViolation<T>> sink) {
-            // Use the same path ordering/equality as before (ConcurrentSkipListMap): comparator-based, not Path#equals.
-            final Map<Path, Set<Object>> pathMap = completedValidations.computeIfAbsent(constraint,
-                    k -> new TreeMap<>(PathImpl.PATH_COMPARATOR));
-            // Read-only use as a comparator-based map key for the duration of this validation; no copy needed.
-            final Set<Object> objectSet =
-                    pathMap.computeIfAbsent(context.pathReference(),
-                            p -> Collections.newSetFromMap(new IdentityHashMap<>()));
-            if (!objectSet.add(context.getValue())) {
-                return true;
-            }
+            // No per-(constraint, path, value) de-duplication is performed here. It is not needed: groups are
+            // validated in a single pass (see GroupStrategy usage in process()), so a given constraint at a
+            // given path/value is reached exactly once, even when it belongs to several targeted groups or a
+            // redefined Default sequence. Distinct locations (e.g. the same shared object cascaded via two
+            // properties) are distinct paths and must each be reported. Cycles are handled separately via
+            // GraphContext#isRecursive(), not by tracking completed validations.
             final ConstraintValidator constraintValidator = getConstraintValidator(constraint);
             final ConstraintValidatorContextImpl<T> constraintValidatorContext =
                     new ConstraintValidatorContextImpl<>(this, constraint);
@@ -590,9 +584,6 @@ public abstract class ValidationJob<T> {
 
     private final Lazy<Set<ConstraintViolation<T>>> results = new Lazy<>(LinkedHashSet::new);
 
-    /** Filled only during single-threaded {@link #getResults()} for one validation. */
-    private Map<ConstraintD<?>, Map<Path, Set<Object>>> completedValidations;
-
     ValidationJob(ApacheFactoryContext validatorContext, Class<?>[] groups) {
         super();
         this.validatorContext = Validate.notNull(validatorContext, "validatorContext");
@@ -609,12 +600,7 @@ public abstract class ValidationJob<T> {
 
             final Consumer<ConstraintViolation<T>> sink = results.consumer(Set::add);
 
-            completedValidations = new HashMap<>();
-            try {
-                baseFrame.process(groups.asStrategy(), sink);
-            } finally {
-                completedValidations = null;
-            }
+            baseFrame.process(groups.asStrategy(), sink);
             if (results.optional().isPresent()) {
                 return Collections.unmodifiableSet(results.get());
             }