diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/MessageInterpolatorContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/MessageInterpolatorContext.java index 52943e563..44be6fe82 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/MessageInterpolatorContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/MessageInterpolatorContext.java @@ -4,8 +4,6 @@ */ package org.hibernate.validator.internal.engine; -import static org.hibernate.validator.internal.util.CollectionHelper.toImmutableMap; - import java.lang.invoke.MethodHandles; import java.util.Map; @@ -47,8 +45,8 @@ public MessageInterpolatorContext(ConstraintDescriptor constraintDescriptor, this.validatedValue = validatedValue; this.rootBeanType = rootBeanType; this.propertyPath = propertyPath; - this.messageParameters = toImmutableMap( messageParameters ); - this.expressionVariables = toImmutableMap( expressionVariables ); + this.messageParameters = messageParameters; + this.expressionVariables = expressionVariables; this.expressionLanguageFeatureLevel = expressionLanguageFeatureLevel; this.customViolation = customViolation; } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java index 5cb9f3ea7..3fecef706 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java @@ -528,6 +528,9 @@ private boolean validateConstraintsForSingleDefaultGroupElement(BaseBeanVali valueContext.setCurrentGroup( defaultSequenceMember.getDefiningClass() ); + BeanValueContext.ValueState originalValueState = valueContext.getCurrentValueState(); + valueContext.appendEmptyNode(); + for ( MetaConstraint metaConstraint : metaConstraints ) { // HV-466, an interface implemented more than one time in the hierarchy has to be validated only one // time. An interface can define more than one constraint, we have to check the class we are validating. @@ -547,6 +550,10 @@ private boolean validateConstraintsForSingleDefaultGroupElement(BaseBeanVali validationSuccessful = validationSuccessful && tmp; } + + // reset the value context to the state before this call + valueContext.resetValueState( originalValueState ); + return validationSuccessful; } @@ -566,18 +573,24 @@ private void validateConstraintsForNonDefaultGroup(BaseBeanValidationContext private boolean validateMetaConstraints(BaseBeanValidationContext validationContext, ValueContext valueContext, Object parent, Iterable> constraints) { boolean validationSuccessful = true; + BeanValueContext.ValueState originalValueState = valueContext.getCurrentValueState(); + valueContext.appendEmptyNode(); + for ( MetaConstraint metaConstraint : constraints ) { validationSuccessful = validateMetaConstraint( validationContext, valueContext, parent, metaConstraint ) && validationSuccessful; if ( shouldFailFast( validationContext ) ) { break; } } + + // reset the value context to the state before this call + valueContext.resetValueState( originalValueState ); + return validationSuccessful; } private boolean validateMetaConstraint(BaseBeanValidationContext validationContext, ValueContext valueContext, Object parent, MetaConstraint metaConstraint) { - BeanValueContext.ValueState originalValueState = valueContext.getCurrentValueState(); - valueContext.appendNode( metaConstraint.getLocation() ); + valueContext.updateNode( metaConstraint.getLocation() ); boolean success = true; if ( isValidationRequired( validationContext, valueContext, metaConstraint ) ) { @@ -591,9 +604,6 @@ private boolean validateMetaConstraint(BaseBeanValidationContext validationCo validationContext.markConstraintProcessed( valueContext, metaConstraint ); } - // reset the value context to the state before this call - valueContext.resetValueState( originalValueState ); - return success; } @@ -691,11 +701,31 @@ private class CascadingValueReceiver implements ValueExtractor.ValueReceiver { private final BaseBeanValidationContext validationContext; private final ValueContext valueContext; private final ContainerCascadingMetaData cascadingMetaData; + private final BeanValueContext cascadedValueContext; public CascadingValueReceiver(BaseBeanValidationContext validationContext, ValueContext valueContext, ContainerCascadingMetaData cascadingMetaData) { this.validationContext = validationContext; this.valueContext = valueContext; this.cascadingMetaData = cascadingMetaData; + this.cascadedValueContext = ValueContexts.getLocalExecutionContextForBean( + valueContext, + validatorScopedContext.getParameterNameProvider(), + null, + null, + valueContext.getPropertyPath() + ); + } + + private BeanValueContext resetCascadedValueContext(Object value) { + Contracts.assertNotNull( value, "value cannot be null" ); + + BeanMetaData currentBeanMetaData = cascadedValueContext.getCurrentBeanMetaData(); + if ( currentBeanMetaData == null || currentBeanMetaData.getBeanClass() != value.getClass() ) { + currentBeanMetaData = beanMetaDataManager.getBeanMetaData( value.getClass() ); + } + cascadedValueContext.reset( value, valueContext.getPropertyPath(), currentBeanMetaData ); + cascadedValueContext.setCurrentValidatedValue( value ); + return cascadedValueContext; } @Override @@ -738,7 +768,7 @@ private void doValidate(Object value, String nodeName) { // already and need only to pass the current element ValidationOrder validationOrder = validationOrderGenerator.getValidationOrder( currentGroup, currentGroup != originalGroup ); - BeanValueContext cascadedValueContext = buildNewLocalExecutionContext( valueContext, value ); + BeanValueContext cascadedValueContext = resetCascadedValueContext( value ); if ( cascadingMetaData.getDeclaredContainerClass() != null ) { cascadedValueContext.setTypeParameter( cascadingMetaData.getDeclaredContainerClass(), cascadingMetaData.getDeclaredTypeParameterIndex() ); @@ -751,14 +781,13 @@ private void doValidate(Object value, String nodeName) { // Cascade validation to container elements if we are dealing with a container element if ( cascadingMetaData.hasContainerElementsMarkedForCascading() ) { - ValueContext cascadedTypeArgumentValueContext = buildNewLocalExecutionContext( valueContext, value ); if ( cascadingMetaData.getTypeParameter() != null ) { cascadedValueContext.setTypeParameter( cascadingMetaData.getDeclaredContainerClass(), cascadingMetaData.getDeclaredTypeParameterIndex() ); } - cascadedTypeArgumentValueContext.appendTypeParameterNode( nodeName ); + cascadedValueContext.appendTypeParameterNode( nodeName ); - validateCascadedContainerElementsInContext( value, validationContext, cascadedTypeArgumentValueContext, cascadingMetaData, validationOrder ); + validateCascadedContainerElementsInContext( value, validationContext, cascadedValueContext, cascadingMetaData, validationOrder ); } } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorContextImpl.java index d9d8595f2..08f3f06fa 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorContextImpl.java @@ -153,7 +153,7 @@ public final List getConstraintViolationCrea throw LOG.getAtLeastOneCustomMessageMustBeCreatedException(); } - return CollectionHelper.toImmutableList( constraintViolationCreationContexts ); + return constraintViolationCreationContexts; } if ( constraintViolationCreationContexts == null || constraintViolationCreationContexts.size() == 0 ) { @@ -165,7 +165,7 @@ public final List getConstraintViolationCrea returnedConstraintViolationCreationContexts.addAll( constraintViolationCreationContexts ); returnedConstraintViolationCreationContexts.add( getDefaultConstraintViolationCreationContext() ); - return CollectionHelper.toImmutableList( returnedConstraintViolationCreationContexts ); + return returnedConstraintViolationCreationContexts; } protected final MutablePath getCopyOfBasePath() { @@ -178,8 +178,8 @@ private ConstraintViolationCreationContext getDefaultConstraintViolationCreation defaultConstraintExpressionLanguageFeatureLevel, false, basePath, - messageParameters != null ? new HashMap<>( messageParameters ) : Collections.emptyMap(), - expressionVariables != null ? new HashMap<>( expressionVariables ) : Collections.emptyMap(), + messageParameters != null ? Map.copyOf( messageParameters ) : Collections.emptyMap(), + expressionVariables != null ? Map.copyOf( expressionVariables ) : Collections.emptyMap(), dynamicPayload ); } @@ -214,8 +214,8 @@ public ConstraintValidatorContext addConstraintViolation() { expressionLanguageFeatureLevel, true, propertyPath, - messageParameters != null ? new HashMap<>( messageParameters ) : Collections.emptyMap(), - expressionVariables != null ? new HashMap<>( expressionVariables ) : Collections.emptyMap(), + messageParameters != null ? Map.copyOf( messageParameters ) : Collections.emptyMap(), + expressionVariables != null ? Map.copyOf( expressionVariables ) : Collections.emptyMap(), dynamicPayload ) ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintViolationCreationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintViolationCreationContext.java index 676ffd302..f03b53930 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintViolationCreationContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintViolationCreationContext.java @@ -4,8 +4,6 @@ */ package org.hibernate.validator.internal.engine.constraintvalidation; -import static org.hibernate.validator.internal.util.CollectionHelper.toImmutableMap; - import java.util.Map; import jakarta.validation.Path; @@ -44,8 +42,8 @@ public ConstraintViolationCreationContext(String message, this.customViolation = customViolation; // at this point we make a copy of the path to avoid side effects this.propertyPath = property.materialize(); - this.messageParameters = toImmutableMap( messageParameters ); - this.expressionVariables = toImmutableMap( expressionVariables ); + this.messageParameters = messageParameters; + this.expressionVariables = expressionVariables; this.dynamicPayload = dynamicPayload; } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/path/MutableNode.java b/engine/src/main/java/org/hibernate/validator/internal/engine/path/MutableNode.java index 481f21f25..220dfe7df 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/path/MutableNode.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/path/MutableNode.java @@ -49,7 +49,6 @@ public class MutableNode static { ROOT_NODE = MutableNode.createBeanNode( null ); - ROOT_NODE.valueSet = true; ROOT_NODE.nodes = new MutableNode[] { ROOT_NODE }; ROOT_NODE.hashCode(); } @@ -66,19 +65,18 @@ public class MutableNode public static final String MAP_KEY_NODE_NAME = ""; public static final String MAP_VALUE_NODE_NAME = ""; - private final String name; private final MutableNode parent; - private final ElementKind kind; private final int size; + private String name; + private ElementKind kind; private boolean isIterable; private Integer index; private Object key; //type-specific attributes private final Class[] parameterTypes; - private final Integer parameterIndex; + private Integer parameterIndex; private Object value; - private boolean valueSet; private Class containerClass; private Integer typeArgumentIndex; @@ -88,7 +86,7 @@ public class MutableNode private MutableNode( String name, MutableNode parent, boolean isIterable, Integer index, Object key, ElementKind kind, Class[] parameterTypes, - Integer parameterIndex, Object value, boolean valueSet, Class containerClass, Integer typeArgumentIndex + Integer parameterIndex, Object value, Class containerClass, Integer typeArgumentIndex ) { this.name = name; this.parent = parent; @@ -96,7 +94,6 @@ private MutableNode( this.index = index; this.key = key; this.value = value; - this.valueSet = valueSet; this.isIterable = isIterable; this.kind = kind; this.parameterTypes = parameterTypes; @@ -105,6 +102,22 @@ private MutableNode( this.typeArgumentIndex = typeArgumentIndex; } + public static MutableNode createNode(MutableNode parent) { + return new MutableNode( + null, + parent, + false, + null, + null, + null, + EMPTY_CLASS_ARRAY, + null, + null, + null, + null + ); + } + //TODO It would be nicer if we could return PropertyNode public static MutableNode createPropertyNode(String name, MutableNode parent) { return new MutableNode( @@ -117,7 +130,6 @@ public static MutableNode createPropertyNode(String name, MutableNode parent) { EMPTY_CLASS_ARRAY, null, null, - false, null, null ); @@ -134,7 +146,6 @@ public static MutableNode createContainerElementNode(String name, MutableNode pa EMPTY_CLASS_ARRAY, null, null, - false, null, null ); @@ -151,7 +162,6 @@ public static MutableNode createParameterNode(String name, MutableNode parent, i EMPTY_CLASS_ARRAY, parameterIndex, null, - false, null, null ); @@ -168,18 +178,17 @@ public static MutableNode createCrossParameterNode(MutableNode parent) { EMPTY_CLASS_ARRAY, null, null, - false, null, null ); } public static MutableNode createMethodNode(String name, MutableNode parent, Class[] parameterTypes) { - return new MutableNode( name, parent, false, null, null, ElementKind.METHOD, parameterTypes, null, null, false, null, null ); + return new MutableNode( name, parent, false, null, null, ElementKind.METHOD, parameterTypes, null, null, null, null ); } public static MutableNode createConstructorNode(String name, MutableNode parent, Class[] parameterTypes) { - return new MutableNode( name, parent, false, null, null, ElementKind.CONSTRUCTOR, parameterTypes, null, null, false, null, null ); + return new MutableNode( name, parent, false, null, null, ElementKind.CONSTRUCTOR, parameterTypes, null, null, null, null ); } public static MutableNode createBeanNode(MutableNode parent) { @@ -193,7 +202,6 @@ public static MutableNode createBeanNode(MutableNode parent) { EMPTY_CLASS_ARRAY, null, null, - false, null, null ); @@ -210,7 +218,6 @@ public static MutableNode createReturnValue(MutableNode parent) { EMPTY_CLASS_ARRAY, null, null, - false, null, null ); @@ -246,9 +253,11 @@ public void setTypeParameter(Class containerClass, Integer typeArgumentIndex) public void reset() { isIterable = false; index = null; + parameterIndex = null; key = null; typeArgumentIndex = null; containerClass = null; + value = null; } @Override @@ -628,6 +637,37 @@ public boolean isSubPathOrContains(MutableNode other) { return curr.isRootPath() && otherCurr.isRootPath(); } + public void resetAsProperty(String resolvedPropertyName) { + reset(); + this.name = resolvedPropertyName; + this.kind = ElementKind.PROPERTY; + } + + public void resetAsBeanNode() { + reset(); + this.kind = ElementKind.BEAN; + this.name = null; + } + + public void resetAsParameter(String parameterName, int index) { + reset(); + this.kind = ElementKind.PARAMETER; + this.name = parameterName; + this.parameterIndex = index; + } + + public void resetAsReturnValue() { + reset(); + this.name = RETURN_VALUE_NODE_NAME; + this.kind = ElementKind.RETURN_VALUE; + } + + public void resetAsCrossParameter() { + reset(); + this.name = CROSS_PARAMETER_NODE_NAME; + this.kind = ElementKind.CROSS_PARAMETER; + } + protected static class NodeIterator implements Iterator { private final MutableNode[] array; private int index; diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/path/MutablePath.java b/engine/src/main/java/org/hibernate/validator/internal/engine/path/MutablePath.java index 680a31b14..03abc04a8 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/path/MutablePath.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/path/MutablePath.java @@ -151,6 +151,11 @@ private void addMethodNode(String name, Class[] parameterTypes) { currentLeafNode = MutableNode.createMethodNode( name, parent, parameterTypes ); } + public void addEmptyNode() { + MutableNode parent = currentLeafNode; + currentLeafNode = MutableNode.createNode( parent ); + } + public void makeLeafNodeIterable() { currentLeafNode.makeIterable(); } @@ -167,8 +172,6 @@ public void setLeafNodeValueIfRequired(Object value) { // The value is only exposed for property and container element nodes if ( currentLeafNode.getKind() == ElementKind.PROPERTY || currentLeafNode.getKind() == ElementKind.CONTAINER_ELEMENT ) { currentLeafNode.setPropertyValue( value ); - - // the property value is not part of the NodeImpl hashCode so we don't need to reset the PathImpl hashCode } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valuecontext/BeanValueContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valuecontext/BeanValueContext.java index 4f929bb68..d70bada6b 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valuecontext/BeanValueContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valuecontext/BeanValueContext.java @@ -23,7 +23,7 @@ public final class BeanValueContext extends ValueContext { /** * The metadata of the current bean. */ - private final BeanMetaData currentBeanMetaData; + private BeanMetaData currentBeanMetaData; /** * When we check whether the bean was validated we need to check that it was validated for the requested group. @@ -43,8 +43,20 @@ public final class BeanValueContext extends ValueContext { this.currentBeanMetaData = currentBeanMetaData; } + @SuppressWarnings("unchecked") public BeanMetaData getCurrentBeanMetaData() { - return currentBeanMetaData; + return (BeanMetaData) currentBeanMetaData; + } + + public void reset(Object currentBean, MutablePath propertyPath, BeanMetaData currentBeanMetaData) { + this.currentBeanMetaData = currentBeanMetaData; + this.currentValidatable = currentBeanMetaData; + this.currentBean = currentBean; + this.propertyPath = propertyPath; + this.alreadyProcessedGroups = null; + this.alreadyProcessedMetaConstraints = null; + this.currentGroup = null; + this.previousGroup = null; } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valuecontext/ValueContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valuecontext/ValueContext.java index 05de9d080..2edc51d57 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valuecontext/ValueContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valuecontext/ValueContext.java @@ -35,12 +35,12 @@ public abstract sealed class ValueContext permits BeanValueContext, Execut /** * The current bean which gets validated. This is the bean hosting the constraints which get validated. */ - protected final T currentBean; + protected Object currentBean; /** * The current property path we are validating. */ - private MutablePath propertyPath; + protected MutablePath propertyPath; /** * The current group we are validating. @@ -57,7 +57,7 @@ public abstract sealed class ValueContext permits BeanValueContext, Execut */ private V currentValue; - private final Validatable currentValidatable; + protected Validatable currentValidatable; /** * The {@code ConstraintLocationKind} the constraint was defined on @@ -80,8 +80,9 @@ public final Class getCurrentGroup() { return currentGroup; } + @SuppressWarnings("unchecked") public final T getCurrentBean() { - return currentBean; + return (T) currentBean; } public Validatable getCurrentValidatable() { @@ -115,6 +116,16 @@ public final void appendTypeParameterNode(String nodeName) { } } + public void appendEmptyNode() { + MutablePath newPath = MutablePath.createCopy( propertyPath ); + newPath.addEmptyNode(); + propertyPath = newPath; + } + + public final void updateNode(ConstraintLocation location) { + location.applyTo( parameterNameProvider, propertyPath ); + } + public final void markCurrentPropertyAsIterable() { propertyPath.makeLeafNodeIterable(); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ValueExtractorResolver.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ValueExtractorResolver.java index 8eb615ea0..a496ac725 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ValueExtractorResolver.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ValueExtractorResolver.java @@ -304,10 +304,12 @@ private Set getRuntimeCompliantValueExtractors(Class possibleValueExtractors = potentialValueExtractorDescriptors - .stream() - .filter( e -> TypeHelper.isAssignable( e.getContainerType(), runtimeType ) ) - .collect( Collectors.toSet() ); + Set possibleValueExtractors = CollectionHelper.newHashSet( potentialValueExtractorDescriptors.size() ); + for ( ValueExtractorDescriptor descriptor : potentialValueExtractorDescriptors ) { + if ( TypeHelper.isAssignable( descriptor.getContainerType(), runtimeType ) ) { + possibleValueExtractors.add( descriptor ); + } + } valueExtractorDescriptors = getMaximallySpecificValueExtractors( possibleValueExtractors ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/AbstractPropertyConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/AbstractPropertyConstraintLocation.java index ebd651300..8046db54d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/AbstractPropertyConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/AbstractPropertyConstraintLocation.java @@ -55,6 +55,11 @@ public void appendTo(ExecutableParameterNameProvider parameterNameProvider, Muta path.addPropertyNode( property.getResolvedPropertyName() ); } + @Override + public void applyTo(ExecutableParameterNameProvider parameterNameProvider, MutablePath path) { + path.getLeafNode().resetAsProperty( property.getResolvedPropertyName() ); + } + @Override public Object getValue(Object parent) { return propertyAccessor.getValueFrom( parent ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/BeanConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/BeanConstraintLocation.java index f2d221012..b8387ce3b 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/BeanConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/BeanConstraintLocation.java @@ -58,6 +58,11 @@ public void appendTo(ExecutableParameterNameProvider parameterNameProvider, Muta path.addBeanNode(); } + @Override + public void applyTo(ExecutableParameterNameProvider parameterNameProvider, MutablePath path) { + path.getLeafNode().resetAsBeanNode(); + } + @Override public Object getValue(Object parent) { return parent; diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java index 40d9d9cf0..5686cd148 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java @@ -90,6 +90,8 @@ static ConstraintLocation forParameter(Callable callable, int index) { */ void appendTo(ExecutableParameterNameProvider parameterNameProvider, MutablePath path); + void applyTo(ExecutableParameterNameProvider parameterNameProvider, MutablePath path); + /** * Obtains the value of this location from the parent. The type of the passed parent depends on the location type, * e.g. a bean would be passed for a {@link AbstractPropertyConstraintLocation} but an diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/CrossParameterConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/CrossParameterConstraintLocation.java index cbf4dcbf8..1f8af2b4d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/CrossParameterConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/CrossParameterConstraintLocation.java @@ -49,6 +49,11 @@ public void appendTo(ExecutableParameterNameProvider parameterNameProvider, Muta path.addCrossParameterNode(); } + @Override + public void applyTo(ExecutableParameterNameProvider parameterNameProvider, MutablePath path) { + path.getLeafNode().resetAsCrossParameter(); + } + @Override public Object getValue(Object parent) { return parent; diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ParameterConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ParameterConstraintLocation.java index 4abfa683c..431d01cd7 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ParameterConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ParameterConstraintLocation.java @@ -57,6 +57,11 @@ public void appendTo(ExecutableParameterNameProvider parameterNameProvider, Muta path.addParameterNode( callable.getParameterName( parameterNameProvider, index ), index ); } + @Override + public void applyTo(ExecutableParameterNameProvider parameterNameProvider, MutablePath path) { + path.getLeafNode().resetAsParameter( callable.getParameterName( parameterNameProvider, index ), index ); + } + @Override public Object getValue(Object parent) { return ( (Object[]) parent )[index]; diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ReturnValueConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ReturnValueConstraintLocation.java index 235bbe129..c7dfd721c 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ReturnValueConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ReturnValueConstraintLocation.java @@ -50,6 +50,11 @@ public void appendTo(ExecutableParameterNameProvider parameterNameProvider, Muta path.addReturnValueNode(); } + @Override + public void applyTo(ExecutableParameterNameProvider parameterNameProvider, MutablePath path) { + path.getLeafNode().resetAsReturnValue(); + } + @Override public Object getValue(Object parent) { return parent; diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/TypeArgumentConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/TypeArgumentConstraintLocation.java index 6a53f8688..8182890c8 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/TypeArgumentConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/TypeArgumentConstraintLocation.java @@ -72,6 +72,11 @@ public void appendTo(ExecutableParameterNameProvider parameterNameProvider, Muta delegate.appendTo( parameterNameProvider, path ); } + @Override + public void applyTo(ExecutableParameterNameProvider parameterNameProvider, MutablePath path) { + delegate.applyTo( parameterNameProvider, path ); + } + @Override public Object getValue(Object parent) { return delegate.getValue( parent ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/CollectionHelper.java b/engine/src/main/java/org/hibernate/validator/internal/util/CollectionHelper.java index b38e49b84..74e69f5d5 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/CollectionHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/CollectionHelper.java @@ -98,6 +98,8 @@ public static Set asSet(T... ts) { *

* NOTE: the resulting list does not allow {@code null} values. * Attempt to convert a list with {@code null}s will result in an exception! + * NOTE: do NOT use this util method at "runtime" as results + * in creating unnecessary copies of arrays! * * @param list the list to convert. * @return the converted list. @@ -112,6 +114,8 @@ public static List toImmutableList(List list) { *

* NOTE: the resulting set does not allow {@code null} values. * Attempt to convert a set with {@code null}s will result in an exception! + * NOTE: do NOT use this util method at "runtime" as results + * in creating unnecessary copies of arrays! * * @param set the set to convert. * @return the converted set. @@ -126,6 +130,8 @@ public static Set toImmutableSet(Set set) { *

* NOTE: the resulting map does not allow {@code null} keys and values . * Attempt to convert a map with {@code null}s (either as key or a value) will result in an exception! + * NOTE: do NOT use this util method at "runtime" as results + * in creating unnecessary copies of arrays! * * @param map the map to convert. * @param the type of the map keys.