|
7 | 7 | import java.lang.invoke.MethodHandles;
|
8 | 8 | import java.util.Collections;
|
9 | 9 | import java.util.HashSet;
|
10 |
| -import java.util.IdentityHashMap; |
11 | 10 | import java.util.Map;
|
12 | 11 | import java.util.Set;
|
13 | 12 |
|
@@ -103,18 +102,6 @@ abstract class AbstractValidationContext<T> implements BaseBeanValidationContext
|
103 | 102 | @Lazy
|
104 | 103 | private Set<BeanPathMetaConstraintProcessedUnit> processedPathUnits;
|
105 | 104 |
|
106 |
| - /** |
107 |
| - * The set of already processed groups per bean ({@link BeanGroupProcessedUnit}). |
108 |
| - */ |
109 |
| - @Lazy |
110 |
| - private Set<BeanGroupProcessedUnit> processedGroupUnits; |
111 |
| - |
112 |
| - /** |
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. |
114 |
| - */ |
115 |
| - @Lazy |
116 |
| - private Map<Object, Set<NodeImpl>> processedPathsPerBean; |
117 |
| - |
118 | 105 | /**
|
119 | 106 | * Contains all failing constraints so far.
|
120 | 107 | */
|
@@ -196,28 +183,19 @@ public ConstraintValidatorFactory getConstraintValidatorFactory() {
|
196 | 183 | }
|
197 | 184 |
|
198 | 185 | @Override
|
199 |
| - public boolean isBeanAlreadyValidated(Object value, Class<?> group, ModifiablePath path) { |
| 186 | + public boolean isBeanAlreadyValidated(Object value, Class<?> group, ValueContext<?, ?> valueContext) { |
200 | 187 | if ( !processedBeanTrackingEnabled ) {
|
201 | 188 | return false;
|
202 | 189 | }
|
203 |
| - |
204 |
| - boolean alreadyValidated = isAlreadyValidatedForCurrentGroup( value, group ); |
205 |
| - |
206 |
| - if ( alreadyValidated ) { |
207 |
| - alreadyValidated = isAlreadyValidatedForPath( value, path.getLeafNode() ); |
208 |
| - } |
209 |
| - |
210 |
| - return alreadyValidated; |
| 190 | + return valueContext.isBeanAlreadyValidated( value, group ); |
211 | 191 | }
|
212 | 192 |
|
213 | 193 | @Override
|
214 | 194 | public void markCurrentBeanAsProcessed(ValueContext<?, ?> valueContext) {
|
215 | 195 | if ( !processedBeanTrackingEnabled ) {
|
216 | 196 | return;
|
217 | 197 | }
|
218 |
| - |
219 |
| - markCurrentBeanAsProcessedForCurrentGroup( valueContext.getCurrentBean(), valueContext.getCurrentGroup() ); |
220 |
| - markCurrentBeanAsProcessedForCurrentPath( valueContext.getCurrentBean(), valueContext.getPropertyPath() ); |
| 198 | + valueContext.markCurrentGroupAsProcessed(); |
221 | 199 | }
|
222 | 200 |
|
223 | 201 | @Override
|
@@ -340,70 +318,13 @@ private String interpolate(
|
340 | 318 | }
|
341 | 319 | }
|
342 | 320 |
|
343 |
| - private boolean isAlreadyValidatedForPath(Object value, NodeImpl path) { |
344 |
| - Set<NodeImpl> pathSet = getInitializedProcessedPathsPerBean().get( value ); |
345 |
| - if ( pathSet == null ) { |
346 |
| - return false; |
347 |
| - } |
348 |
| - |
349 |
| - if ( path.isRootPath() ) { |
350 |
| - return true; |
351 |
| - } |
352 |
| - |
353 |
| - // Since this isAlreadyValidatedForPath(..) is only applicable for an object that is about to be cascaded into, |
354 |
| - // it means that the new path we are testing cannot be a root path; also since we are cascading into inner |
355 |
| - // objects, i.e. going further from the object tree root, it means that the new path cannot be shorter than |
356 |
| - // the ones we've already encountered. |
357 |
| - for ( NodeImpl p : pathSet ) { |
358 |
| - if ( p.isSubPathOrContains( path ) ) { |
359 |
| - return true; |
360 |
| - } |
361 |
| - } |
362 |
| - return false; |
363 |
| - } |
364 |
| - |
365 |
| - private boolean isAlreadyValidatedForCurrentGroup(Object value, Class<?> group) { |
366 |
| - return getInitializedProcessedGroupUnits().contains( new BeanGroupProcessedUnit( value, group ) ); |
367 |
| - } |
368 |
| - |
369 |
| - private void markCurrentBeanAsProcessedForCurrentPath(Object bean, ModifiablePath path) { |
370 |
| - Map<Object, Set<NodeImpl>> processedPathsPerBean = getInitializedProcessedPathsPerBean(); |
371 |
| - |
372 |
| - Set<NodeImpl> processedPaths = processedPathsPerBean.get( bean ); |
373 |
| - if ( processedPaths == null ) { |
374 |
| - processedPaths = new HashSet<>(); |
375 |
| - processedPathsPerBean.put( bean, processedPaths ); |
376 |
| - } |
377 |
| - |
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 |
| - } |
381 |
| - |
382 |
| - private void markCurrentBeanAsProcessedForCurrentGroup(Object bean, Class<?> group) { |
383 |
| - getInitializedProcessedGroupUnits().add( new BeanGroupProcessedUnit( bean, group ) ); |
384 |
| - } |
385 |
| - |
386 | 321 | private Set<BeanPathMetaConstraintProcessedUnit> getInitializedProcessedPathUnits() {
|
387 | 322 | if ( processedPathUnits == null ) {
|
388 | 323 | processedPathUnits = new HashSet<>();
|
389 | 324 | }
|
390 | 325 | return processedPathUnits;
|
391 | 326 | }
|
392 | 327 |
|
393 |
| - private Set<BeanGroupProcessedUnit> getInitializedProcessedGroupUnits() { |
394 |
| - if ( processedGroupUnits == null ) { |
395 |
| - processedGroupUnits = new HashSet<>(); |
396 |
| - } |
397 |
| - return processedGroupUnits; |
398 |
| - } |
399 |
| - |
400 |
| - private Map<Object, Set<NodeImpl>> getInitializedProcessedPathsPerBean() { |
401 |
| - if ( processedPathsPerBean == null ) { |
402 |
| - processedPathsPerBean = new IdentityHashMap<>(); |
403 |
| - } |
404 |
| - return processedPathsPerBean; |
405 |
| - } |
406 |
| - |
407 | 328 | private Set<ConstraintViolation<T>> getInitializedFailingConstraintViolations() {
|
408 | 329 | if ( failingConstraintViolations == null ) {
|
409 | 330 | failingConstraintViolations = new HashSet<>();
|
@@ -462,48 +383,4 @@ private int createHashCode() {
|
462 | 383 | }
|
463 | 384 | }
|
464 | 385 |
|
465 |
| - private static final class BeanGroupProcessedUnit { |
466 |
| - |
467 |
| - // these fields are final but we don't mark them as final as an optimization |
468 |
| - private Object bean; |
469 |
| - private Class<?> group; |
470 |
| - private int hashCode; |
471 |
| - |
472 |
| - BeanGroupProcessedUnit(Object bean, Class<?> group) { |
473 |
| - this.bean = bean; |
474 |
| - this.group = group; |
475 |
| - this.hashCode = createHashCode(); |
476 |
| - } |
477 |
| - |
478 |
| - @Override |
479 |
| - public boolean equals(Object o) { |
480 |
| - // null check intentionally left out |
481 |
| - if ( this == o ) { |
482 |
| - return true; |
483 |
| - } |
484 |
| - |
485 |
| - // No need to check if the class matches because of how this class is used in the set. |
486 |
| - BeanGroupProcessedUnit that = (BeanGroupProcessedUnit) o; |
487 |
| - |
488 |
| - if ( bean != that.bean ) { // instance equality |
489 |
| - return false; |
490 |
| - } |
491 |
| - if ( !group.equals( that.group ) ) { |
492 |
| - return false; |
493 |
| - } |
494 |
| - |
495 |
| - return true; |
496 |
| - } |
497 |
| - |
498 |
| - @Override |
499 |
| - public int hashCode() { |
500 |
| - return hashCode; |
501 |
| - } |
502 |
| - |
503 |
| - private int createHashCode() { |
504 |
| - int result = System.identityHashCode( bean ); |
505 |
| - result = 31 * result + group.hashCode(); |
506 |
| - return result; |
507 |
| - } |
508 |
| - } |
509 | 386 | }
|
0 commit comments