All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hibernate.validator.internal.engine.ValidationContext Maven / Gradle / Ivy

Go to download

JSR 380's RI, Hibernate Validator version ${hibernate-validator.version} and its dependencies repackaged as OSGi bundle

There is a newer version: 5.1.0
Show newest version
/*
 * Hibernate Validator, declare and validate application constraints
 *
 * License: Apache License, Version 2.0
 * See the license.txt file in the root directory or .
 */
package org.hibernate.validator.internal.engine;

import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet;

import java.lang.invoke.MethodHandles;
import java.lang.reflect.Executable;
import java.time.Duration;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import javax.validation.ClockProvider;
import javax.validation.ConstraintValidatorFactory;
import javax.validation.ConstraintViolation;
import javax.validation.MessageInterpolator;
import javax.validation.ParameterNameProvider;
import javax.validation.Path;
import javax.validation.TraversableResolver;
import javax.validation.ValidationException;
import javax.validation.Validator;
import javax.validation.metadata.ConstraintDescriptor;

import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext;
import org.hibernate.validator.internal.engine.ValidatorFactoryImpl.ValidatorFactoryScopedContext;
import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl;
import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager;
import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintViolationCreationContext;
import org.hibernate.validator.internal.engine.path.PathImpl;
import org.hibernate.validator.internal.metadata.BeanMetaDataManager;
import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData;
import org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData;
import org.hibernate.validator.internal.metadata.core.MetaConstraint;
import org.hibernate.validator.internal.metadata.facets.Validatable;
import org.hibernate.validator.internal.util.ExecutableParameterNameProvider;
import org.hibernate.validator.internal.util.logging.Log;
import org.hibernate.validator.internal.util.logging.LoggerFactory;
import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory;

/**
 * Context object keeping track of all required data for a validation call.
 *
 * We use this object to collect all failing constraints, but also to have access to resources like
 * constraint validator factory, message interpolator, traversable resolver, etc.
 *
 * @author Hardy Ferentschik
 * @author Emmanuel Bernard
 * @author Gunnar Morling
 * @author Guillaume Smet
 */
public class ValidationContext {

	private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() );

	/**
	 * The current validation operation (e.g. bean validation, parameter validation).
	 */
	private final ValidationOperation validationOperation;

	/**
	 * Caches and manages life cycle of constraint validator instances.
	 */
	private final ConstraintValidatorManager constraintValidatorManager;

	/**
	 * The root bean of the validation.
	 */
	private final T rootBean;

	/**
	 * The root bean class of the validation.
	 */
	private final Class rootBeanClass;

	/**
	 * The metadata of the root bean.
	 */
	private final BeanMetaData rootBeanMetaData;

	/**
	 * The method of the current validation call in case of executable validation.
	 */
	private final Executable executable;

	/**
	 * The validated parameters in case of executable parameter validation.
	 */
	private final Object[] executableParameters;

	/**
	 * The validated return value in case of executable return value validation.
	 */
	private final Object executableReturnValue;

	/**
	 * The metadata of the Executable. Will be non empty if we are in the case of method validation and the method is constrained.
	 */
	private final Optional executableMetaData;

	/**
	 * The set of already processed meta constraints per bean - path ({@link BeanPathMetaConstraintProcessedUnit}).
	 */
	private final Set processedPathUnits;

	/**
	 * The set of already processed groups per bean ({@link BeanGroupProcessedUnit}).
	 */
	private final Set processedGroupUnits;

	/**
	 * Maps an object to a list of paths in which it has been validated. The objects are the bean instances.
	 */
	private final Map> processedPathsPerBean;

	/**
	 * Contains all failing constraints so far.
	 */
	private final Set> failingConstraintViolations;

	/**
	 * The constraint factory which should be used in this context.
	 */
	private final ConstraintValidatorFactory constraintValidatorFactory;

	/**
	 * Context containing all {@link Validator} level helpers and configuration properties.
	 */
	private final ValidatorScopedContext validatorScopedContext;

	/**
	 * Allows a JPA provider to decide whether a property should be validated.
	 */
	private final TraversableResolver traversableResolver;

	/**
	 * The constraint validator initialization context.
	 */
	private final HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext;

	/**
	 * Indicates if the tracking of already validated bean should be disabled.
	 */
	private final boolean disableAlreadyValidatedBeanTracking;

	/**
	 * The name of the validated (leaf) property in case of a validateProperty()/validateValue() call.
	 */
	private String validatedProperty;

	private ValidationContext(ValidationOperation validationOperation,
			ConstraintValidatorManager constraintValidatorManager,
			ConstraintValidatorFactory constraintValidatorFactory,
			ValidatorScopedContext validatorScopedContext,
			TraversableResolver traversableResolver,
			HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext,
			T rootBean,
			Class rootBeanClass,
			BeanMetaData rootBeanMetaData,
			Executable executable,
			Object[] executableParameters,
			Object executableReturnValue,
			Optional executableMetaData) {
		this.validationOperation = validationOperation;

		this.constraintValidatorManager = constraintValidatorManager;
		this.validatorScopedContext = validatorScopedContext;
		this.constraintValidatorFactory = constraintValidatorFactory;
		this.traversableResolver = traversableResolver;
		this.constraintValidatorInitializationContext = constraintValidatorInitializationContext;

		this.rootBean = rootBean;
		this.rootBeanClass = rootBeanClass;
		this.rootBeanMetaData = rootBeanMetaData;
		this.executable = executable;
		this.executableParameters = executableParameters;
		this.executableReturnValue = executableReturnValue;

		this.processedGroupUnits = new HashSet<>();
		this.processedPathUnits = new HashSet<>();
		this.processedPathsPerBean = new IdentityHashMap<>();
		this.failingConstraintViolations = newHashSet();

		this.executableMetaData = executableMetaData;

		this.disableAlreadyValidatedBeanTracking = buildDisableAlreadyValidatedBeanTracking( validationOperation, rootBeanMetaData, executableMetaData );
	}

	public static ValidationContextBuilder getValidationContextBuilder(
			BeanMetaDataManager beanMetaDataManager,
			ConstraintValidatorManager constraintValidatorManager,
			ConstraintValidatorFactory constraintValidatorFactory,
			ValidatorScopedContext validatorScopedContext,
			TraversableResolver traversableResolver,
			HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext) {

		return new ValidationContextBuilder(
				beanMetaDataManager,
				constraintValidatorManager,
				constraintValidatorFactory,
				validatorScopedContext,
				traversableResolver,
				constraintValidatorInitializationContext
		);
	}

	public T getRootBean() {
		return rootBean;
	}

	public Class getRootBeanClass() {
		return rootBeanClass;
	}

	public BeanMetaData getRootBeanMetaData() {
		return rootBeanMetaData;
	}

	public Executable getExecutable() {
		return executable;
	}

	public Optional getExecutableMetaData() {
		return executableMetaData;
	}

	public TraversableResolver getTraversableResolver() {
		return traversableResolver;
	}

	public boolean isFailFastModeEnabled() {
		return validatorScopedContext.isFailFast();
	}

	public ConstraintValidatorManager getConstraintValidatorManager() {
		return constraintValidatorManager;
	}

	/**
	 * Returns a list with the current executable's parameter names as retrieved
	 * from the current {@link ParameterNameProvider}.
	 *
	 * @return The current executable's parameter names,if this context was
	 * created for parameter validation, {@code null} otherwise.
	 */
	public List getParameterNames() {
		if ( !ValidationOperation.PARAMETER_VALIDATION.equals( validationOperation ) ) {
			return null;
		}

		return validatorScopedContext.getParameterNameProvider().getParameterNames( executable );
	}

	public ClockProvider getClockProvider() {
		return validatorScopedContext.getClockProvider();
	}

	public Object getConstraintValidatorPayload() {
		return validatorScopedContext.getConstraintValidatorPayload();
	}

	public HibernateConstraintValidatorInitializationContext getConstraintValidatorInitializationContext() {
		return constraintValidatorInitializationContext;
	}

	public Set> createConstraintViolations(ValueContext localContext,
			ConstraintValidatorContextImpl constraintValidatorContext) {

		return constraintValidatorContext.getConstraintViolationCreationContexts().stream()
			.map( c -> createConstraintViolation( localContext, c, constraintValidatorContext.getConstraintDescriptor() ) )
			.collect( Collectors.toSet() );
	}

	public ConstraintValidatorFactory getConstraintValidatorFactory() {
		return constraintValidatorFactory;
	}

	public boolean isBeanAlreadyValidated(Object value, Class group, PathImpl path) {
		if ( disableAlreadyValidatedBeanTracking ) {
			return false;
		}

		boolean alreadyValidated;
		alreadyValidated = isAlreadyValidatedForCurrentGroup( value, group );

		if ( alreadyValidated ) {
			alreadyValidated = isAlreadyValidatedForPath( value, path );
		}

		return alreadyValidated;
	}

	public void markCurrentBeanAsProcessed(ValueContext valueContext) {
		if ( disableAlreadyValidatedBeanTracking ) {
			return;
		}

		markCurrentBeanAsProcessedForCurrentGroup( valueContext.getCurrentBean(), valueContext.getCurrentGroup() );
		markCurrentBeanAsProcessedForCurrentPath( valueContext.getCurrentBean(), valueContext.getPropertyPath() );
	}

	public void addConstraintFailures(Set> failingConstraintViolations) {
		this.failingConstraintViolations.addAll( failingConstraintViolations );
	}

	public Set> getFailingConstraints() {
		return failingConstraintViolations;
	}


	public ConstraintViolation createConstraintViolation(ValueContext localContext, ConstraintViolationCreationContext constraintViolationCreationContext, ConstraintDescriptor descriptor) {
		String messageTemplate = constraintViolationCreationContext.getMessage();
		String interpolatedMessage = interpolate(
				messageTemplate,
				localContext.getCurrentValidatedValue(),
				descriptor,
				constraintViolationCreationContext.getMessageParameters(),
				constraintViolationCreationContext.getExpressionVariables()
		);
		// at this point we make a copy of the path to avoid side effects
		Path path = PathImpl.createCopy( constraintViolationCreationContext.getPath() );
		Object dynamicPayload = constraintViolationCreationContext.getDynamicPayload();

		switch ( validationOperation ) {
			case PARAMETER_VALIDATION:
				return ConstraintViolationImpl.forParameterValidation(
						messageTemplate,
						constraintViolationCreationContext.getMessageParameters(),
						constraintViolationCreationContext.getExpressionVariables(),
						interpolatedMessage,
						getRootBeanClass(),
						getRootBean(),
						localContext.getCurrentBean(),
						localContext.getCurrentValidatedValue(),
						path,
						descriptor,
						localContext.getElementType(),
						executableParameters,
						dynamicPayload
				);
			case RETURN_VALUE_VALIDATION:
				return ConstraintViolationImpl.forReturnValueValidation(
						messageTemplate,
						constraintViolationCreationContext.getMessageParameters(),
						constraintViolationCreationContext.getExpressionVariables(),
						interpolatedMessage,
						getRootBeanClass(),
						getRootBean(),
						localContext.getCurrentBean(),
						localContext.getCurrentValidatedValue(),
						path,
						descriptor,
						localContext.getElementType(),
						executableReturnValue,
						dynamicPayload
				);
			default:
				return ConstraintViolationImpl.forBeanValidation(
						messageTemplate,
						constraintViolationCreationContext.getMessageParameters(),
						constraintViolationCreationContext.getExpressionVariables(),
						interpolatedMessage,
						getRootBeanClass(),
						getRootBean(),
						localContext.getCurrentBean(),
						localContext.getCurrentValidatedValue(),
						path,
						descriptor,
						localContext.getElementType(),
						dynamicPayload
				);
		}
	}

	public boolean hasMetaConstraintBeenProcessed(Object bean, Path path, MetaConstraint metaConstraint) {
		// this is only useful if the constraint is defined for more than 1 group as in the case it's only
		// defined for one group, there is no chance it's going to be called twice.
		if ( metaConstraint.isDefinedForOneGroupOnly() ) {
			return false;
		}

		return processedPathUnits.contains( new BeanPathMetaConstraintProcessedUnit( bean, path, metaConstraint ) );
	}

	public void markConstraintProcessed(Object bean, Path path, MetaConstraint metaConstraint) {
		// this is only useful if the constraint is defined for more than 1 group as in the case it's only
		// defined for one group, there is no chance it's going to be called twice.
		if ( metaConstraint.isDefinedForOneGroupOnly()  ) {
			return;
		}

		processedPathUnits.add( new BeanPathMetaConstraintProcessedUnit( bean, path, metaConstraint ) );
	}

	public String getValidatedProperty() {
		return validatedProperty;
	}

	public void setValidatedProperty(String validatedProperty) {
		this.validatedProperty = validatedProperty;
	}

	@Override
	public String toString() {
		final StringBuilder sb = new StringBuilder();
		sb.append( "ValidationContext" );
		sb.append( "{rootBean=" ).append( rootBean );
		sb.append( '}' );
		return sb.toString();
	}

	private static boolean buildDisableAlreadyValidatedBeanTracking(ValidationOperation validationOperation, BeanMetaData rootBeanMetaData,
			Optional executableMetaData) {
		Validatable validatable;
		switch ( validationOperation ) {
			case BEAN_VALIDATION:
			case PROPERTY_VALIDATION:
			case VALUE_VALIDATION:
				// note that in the case of property and value validation, we are considering the root bean, whereas we
				// could consider the bean of the property or the value. We don't really have the info here though so it
				// will do for now.
				validatable = rootBeanMetaData;
				break;
			case PARAMETER_VALIDATION:
				if ( !executableMetaData.isPresent() ) {
					// the method is unconstrained so there's no need to worry about the tracking
					return false;
				}
				validatable = executableMetaData.get().getValidatableParametersMetaData();
				break;
			case RETURN_VALUE_VALIDATION:
				if ( !executableMetaData.isPresent() ) {
					// the method is unconstrained so there's no need to worry about the tracking
					return false;
				}
				validatable = executableMetaData.get().getReturnValueMetaData();
				break;
			default:
				return false;
		}

		return !validatable.hasCascadables();
	}

	private String interpolate(String messageTemplate,
			Object validatedValue,
			ConstraintDescriptor descriptor,
			Map messageParameters,
			Map expressionVariables) {
		MessageInterpolatorContext context = new MessageInterpolatorContext(
				descriptor,
				validatedValue,
				getRootBeanClass(),
				messageParameters,
				expressionVariables
		);

		try {
			return validatorScopedContext.getMessageInterpolator().interpolate(
					messageTemplate,
					context
			);
		}
		catch (ValidationException ve) {
			throw ve;
		}
		catch (Exception e) {
			throw LOG.getExceptionOccurredDuringMessageInterpolationException( e );
		}
	}

	private boolean isAlreadyValidatedForPath(Object value, PathImpl path) {
		Set pathSet = processedPathsPerBean.get( value );
		if ( pathSet == null ) {
			return false;
		}

		for ( PathImpl p : pathSet ) {
			if ( path.isRootPath() || p.isRootPath() || isSubPathOf( path, p ) || isSubPathOf( p, path ) ) {
				return true;
			}
		}

		return false;
	}

	private boolean isSubPathOf(Path p1, Path p2) {
		Iterator p1Iter = p1.iterator();
		Iterator p2Iter = p2.iterator();
		while ( p1Iter.hasNext() ) {
			Path.Node p1Node = p1Iter.next();
			if ( !p2Iter.hasNext() ) {
				return false;
			}
			Path.Node p2Node = p2Iter.next();
			if ( !p1Node.equals( p2Node ) ) {
				return false;
			}
		}
		return true;
	}

	private boolean isAlreadyValidatedForCurrentGroup(Object value, Class group) {
		return processedGroupUnits.contains( new BeanGroupProcessedUnit( value, group ) );
	}

	private void markCurrentBeanAsProcessedForCurrentPath(Object bean, PathImpl path) {
		// HV-1031 The path object is mutated as we traverse the object tree, hence copy it before saving it
		processedPathsPerBean.computeIfAbsent( bean, b -> new HashSet<>() )
				.add( PathImpl.createCopy( path ) );
	}

	private void markCurrentBeanAsProcessedForCurrentGroup(Object bean, Class group) {
		processedGroupUnits.add( new BeanGroupProcessedUnit( bean, group ) );
	}

	/**
	 * Builder for creating {@link ValidationContext}s suited for the different kinds of validation.
	 *
	 * @author Gunnar Morling
	 */
	public static class ValidationContextBuilder {
		private final BeanMetaDataManager beanMetaDataManager;
		private final ConstraintValidatorManager constraintValidatorManager;
		private final ConstraintValidatorFactory constraintValidatorFactory;
		private final TraversableResolver traversableResolver;
		private final HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext;
		private final ValidatorScopedContext validatorScopedContext;

		private ValidationContextBuilder(
				BeanMetaDataManager beanMetaDataManager,
				ConstraintValidatorManager constraintValidatorManager,
				ConstraintValidatorFactory constraintValidatorFactory,
				ValidatorScopedContext validatorScopedContext,
				TraversableResolver traversableResolver,
				HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext) {
			this.beanMetaDataManager = beanMetaDataManager;
			this.constraintValidatorManager = constraintValidatorManager;
			this.constraintValidatorFactory = constraintValidatorFactory;
			this.traversableResolver = traversableResolver;
			this.constraintValidatorInitializationContext = constraintValidatorInitializationContext;
			this.validatorScopedContext = validatorScopedContext;
		}

		public  ValidationContext forValidate(T rootBean) {
			@SuppressWarnings("unchecked")
			Class rootBeanClass = (Class) rootBean.getClass();
			return new ValidationContext<>(
					ValidationOperation.BEAN_VALIDATION,
					constraintValidatorManager,
					constraintValidatorFactory,
					validatorScopedContext,
					traversableResolver,
					constraintValidatorInitializationContext,
					rootBean,
					rootBeanClass,
					beanMetaDataManager.getBeanMetaData( rootBeanClass ),
					null, //executable
					null, //executable parameters
					null, //executable return value
					null //executable metadata
			);
		}

		public  ValidationContext forValidateProperty(T rootBean) {
			@SuppressWarnings("unchecked")
			Class rootBeanClass = (Class) rootBean.getClass();
			return new ValidationContext<>(
					ValidationOperation.PROPERTY_VALIDATION,
					constraintValidatorManager,
					constraintValidatorFactory,
					validatorScopedContext,
					traversableResolver,
					constraintValidatorInitializationContext,
					rootBean,
					rootBeanClass,
					beanMetaDataManager.getBeanMetaData( rootBeanClass ),
					null, //executable
					null, //executable parameters
					null, //executable return value
					null //executable metadata
			);
		}

		public  ValidationContext forValidateValue(Class rootBeanClass) {
			return new ValidationContext<>(
					ValidationOperation.VALUE_VALIDATION,
					constraintValidatorManager,
					constraintValidatorFactory,
					validatorScopedContext,
					traversableResolver,
					constraintValidatorInitializationContext,
					null, //root bean
					rootBeanClass,
					beanMetaDataManager.getBeanMetaData( rootBeanClass ),
					null, //executable
					null, //executable parameters
					null, //executable return value
					null //executable metadata
			);
		}

		public  ValidationContext forValidateParameters(
				ExecutableParameterNameProvider parameterNameProvider,
				T rootBean,
				Executable executable,
				Object[] executableParameters) {
			@SuppressWarnings("unchecked")
			Class rootBeanClass = rootBean != null ? (Class) rootBean.getClass() : (Class) executable.getDeclaringClass();
			BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass );

			return new ValidationContext<>(
					ValidationOperation.PARAMETER_VALIDATION,
					constraintValidatorManager,
					constraintValidatorFactory,
					validatorScopedContext,
					traversableResolver,
					constraintValidatorInitializationContext,
					rootBean,
					rootBeanClass,
					rootBeanMetaData,
					executable,
					executableParameters,
					null, //executable return value
					rootBeanMetaData.getMetaDataFor( executable )
			);
		}

		public  ValidationContext forValidateReturnValue(
				T rootBean,
				Executable executable,
				Object executableReturnValue) {
			@SuppressWarnings("unchecked")
			Class rootBeanClass = rootBean != null ? (Class) rootBean.getClass() : (Class) executable.getDeclaringClass();
			BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass );
			return new ValidationContext<>(
					ValidationOperation.RETURN_VALUE_VALIDATION,
					constraintValidatorManager,
					constraintValidatorFactory,
					validatorScopedContext,
					traversableResolver,
					constraintValidatorInitializationContext,
					rootBean,
					rootBeanClass,
					beanMetaDataManager.getBeanMetaData( rootBeanClass ),
					executable,
					null, //executable parameters
					executableReturnValue,
					rootBeanMetaData.getMetaDataFor( executable )
			);
		}
	}

	private static final class BeanGroupProcessedUnit {

		// these fields are final but we don't mark them as final as an optimization
		private Object bean;
		private Class group;
		private int hashCode;

		private BeanGroupProcessedUnit(Object bean, Class group) {
			this.bean = bean;
			this.group = group;
			this.hashCode = createHashCode();
		}

		@Override
		public boolean equals(Object o) {
			if ( this == o ) {
				return true;
			}

			// No need to check if the class matches because of how this class is used in the set.
			BeanGroupProcessedUnit that = (BeanGroupProcessedUnit) o;

			if ( bean != that.bean ) {  // instance equality
				return false;
			}
			if ( !group.equals( that.group ) ) {
				return false;
			}

			return true;
		}

		@Override
		public int hashCode() {
			return hashCode;
		}

		private int createHashCode() {
			int result = System.identityHashCode( bean );
			result = 31 * result + group.hashCode();
			return result;
		}
	}

	private static final class BeanPathMetaConstraintProcessedUnit {

		// these fields are final but we don't mark them as final as an optimization
		private Object bean;
		private Path path;
		private MetaConstraint metaConstraint;
		private int hashCode;

		private BeanPathMetaConstraintProcessedUnit(Object bean, Path path, MetaConstraint metaConstraint) {
			this.bean = bean;
			this.path = path;
			this.metaConstraint = metaConstraint;
			this.hashCode = createHashCode();
		}

		@Override
		public boolean equals(Object o) {
			if ( this == o ) {
				return true;
			}

			// No need to check if the class matches because of how this class is used in the set.
			BeanPathMetaConstraintProcessedUnit that = (BeanPathMetaConstraintProcessedUnit) o;

			if ( bean != that.bean ) {  // instance equality
				return false;
			}
			if ( metaConstraint != that.metaConstraint ) {
				return false;
			}
			if ( !path.equals( that.path ) ) {
				return false;
			}

			return true;
		}

		@Override
		public int hashCode() {
			return hashCode;
		}

		private int createHashCode() {
			int result = System.identityHashCode( bean );
			result = 31 * result + path.hashCode();
			result = 31 * result + System.identityHashCode( metaConstraint );
			return result;
		}
	}

	/**
	 * Context object storing the {@link Validator} level helper and configuration properties.
	 * 

* There should be only one per {@code Validator} instance. */ static class ValidatorScopedContext { /** * The message interpolator. */ private final MessageInterpolator messageInterpolator; /** * The parameter name provider. */ private final ExecutableParameterNameProvider parameterNameProvider; /** * Provider for the current time when validating {@code @Future} or {@code @Past} */ private final ClockProvider clockProvider; /** * Defines the temporal validation tolerance i.e. the allowed margin of error when comparing date/time in temporal * constraints. */ private final Duration temporalValidationTolerance; /** * Used to get the {@code ScriptEvaluatorFactory} when validating {@code @ScriptAssert} and * {@code @ParameterScriptAssert} constraints. */ private final ScriptEvaluatorFactory scriptEvaluatorFactory; /** * Hibernate Validator specific flag to abort validation on first constraint violation. */ private final boolean failFast; /** * Hibernate Validator specific flag to disable the {@code TraversableResolver} result cache. */ private final boolean traversableResolverResultCacheEnabled; /** * Hibernate Validator specific payload passed to the constraint validators. */ private final Object constraintValidatorPayload; ValidatorScopedContext(ValidatorFactoryScopedContext validatorFactoryScopedContext) { this.messageInterpolator = validatorFactoryScopedContext.getMessageInterpolator(); this.parameterNameProvider = validatorFactoryScopedContext.getParameterNameProvider(); this.clockProvider = validatorFactoryScopedContext.getClockProvider(); this.temporalValidationTolerance = validatorFactoryScopedContext.getTemporalValidationTolerance(); this.scriptEvaluatorFactory = validatorFactoryScopedContext.getScriptEvaluatorFactory(); this.failFast = validatorFactoryScopedContext.isFailFast(); this.traversableResolverResultCacheEnabled = validatorFactoryScopedContext.isTraversableResolverResultCacheEnabled(); this.constraintValidatorPayload = validatorFactoryScopedContext.getConstraintValidatorPayload(); } public MessageInterpolator getMessageInterpolator() { return this.messageInterpolator; } public ExecutableParameterNameProvider getParameterNameProvider() { return this.parameterNameProvider; } public ClockProvider getClockProvider() { return this.clockProvider; } public Duration getTemporalValidationTolerance() { return this.temporalValidationTolerance; } public ScriptEvaluatorFactory getScriptEvaluatorFactory() { return this.scriptEvaluatorFactory; } public boolean isFailFast() { return this.failFast; } public boolean isTraversableResolverResultCacheEnabled() { return this.traversableResolverResultCacheEnabled; } public Object getConstraintValidatorPayload() { return this.constraintValidatorPayload; } } /** * The different validation operations that can occur. */ private enum ValidationOperation { BEAN_VALIDATION, PROPERTY_VALIDATION, VALUE_VALIDATION, PARAMETER_VALIDATION, RETURN_VALUE_VALIDATION } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy