org.hibernate.validator.internal.metadata.aggregated.ContainerCascadingMetaData Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bean-validator Show documentation
Show all versions of bean-validator Show documentation
JSR 380's RI, Hibernate Validator version ${hibernate-validator.version} and its dependencies repackaged as OSGi bundle
/*
* 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.metadata.aggregated;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import javax.validation.metadata.GroupConversionDescriptor;
import org.hibernate.validator.internal.engine.valueextraction.AnnotatedObject;
import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorDescriptor;
import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager;
import org.hibernate.validator.internal.util.CollectionHelper;
import org.hibernate.validator.internal.util.StringHelper;
import org.hibernate.validator.internal.util.TypeVariables;
import org.hibernate.validator.internal.util.logging.Log;
import org.hibernate.validator.internal.util.logging.LoggerFactory;
import org.hibernate.validator.internal.util.stereotypes.Immutable;
/**
* An aggregated view of the cascading validation metadata for containers. Note that it also includes the cascading
* validation metadata defined on the root element via the {@link AnnotatedObject} pseudo type parameter.
*
* @author Guillaume Smet
*/
public class ContainerCascadingMetaData implements CascadingMetaData {
private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() );
/**
* The enclosing type that defines this type parameter.
*/
private final Type enclosingType;
/**
* The type parameter.
*/
private final TypeVariable typeParameter;
/**
* The declared container class: it is the one used in the node of the property path.
*/
private final Class declaredContainerClass;
/**
* The declared type parameter: it is the one used in the node of the property path.
*/
private final TypeVariable declaredTypeParameter;
/**
* Index of the declared type parameter: it is the one used in the node of the property path.
* It is cached here for performance reasons.
*/
private final Integer declaredTypeParameterIndex;
/**
* Possibly the cascading type parameters corresponding to this type parameter if it is a parameterized type.
*/
@Immutable
private final List containerElementTypesCascadingMetaData;
/**
* If this type parameter is marked for cascading.
*/
private final boolean cascading;
/**
* The group conversions defined for this type parameter.
*/
private GroupConversionHelper groupConversionHelper;
/**
* Whether any container element (it can be nested) is marked for cascaded validation.
*/
private final boolean hasContainerElementsMarkedForCascading;
/**
* The set of value extractors which are type compliant and container element compliant with the element where
* the cascaded validation was declared. The final value extractor is chosen among these ones, based on the
* runtime type.
*/
private final Set valueExtractorCandidates;
public static ContainerCascadingMetaData of(ValueExtractorManager valueExtractorManager, CascadingMetaDataBuilder cascadingMetaDataBuilder,
Object context) {
return new ContainerCascadingMetaData( valueExtractorManager, cascadingMetaDataBuilder );
}
private ContainerCascadingMetaData(ValueExtractorManager valueExtractorManager, CascadingMetaDataBuilder cascadingMetaDataBuilder) {
this(
valueExtractorManager,
cascadingMetaDataBuilder.getEnclosingType(),
cascadingMetaDataBuilder.getTypeParameter(),
cascadingMetaDataBuilder.getDeclaredContainerClass(),
cascadingMetaDataBuilder.getDeclaredTypeParameter(),
cascadingMetaDataBuilder.getContainerElementTypesCascadingMetaData().entrySet().stream()
.map( entry -> new ContainerCascadingMetaData( valueExtractorManager, entry.getValue() ) )
.collect( Collectors.collectingAndThen( Collectors.toList(), CollectionHelper::toImmutableList ) ),
cascadingMetaDataBuilder.isCascading(),
GroupConversionHelper.of( cascadingMetaDataBuilder.getGroupConversions() ),
cascadingMetaDataBuilder.isMarkedForCascadingOnAnnotatedObjectOrContainerElements()
);
}
private ContainerCascadingMetaData(ValueExtractorManager valueExtractorManager, Type enclosingType, TypeVariable typeParameter,
Class declaredContainerClass, TypeVariable declaredTypeParameter, List containerElementTypesCascadingMetaData,
boolean cascading, GroupConversionHelper groupConversionHelper, boolean markedForCascadingOnContainerElements) {
this.enclosingType = enclosingType;
this.typeParameter = typeParameter;
this.declaredContainerClass = declaredContainerClass;
this.declaredTypeParameter = declaredTypeParameter;
this.declaredTypeParameterIndex = TypeVariables.getTypeParameterIndex( declaredTypeParameter );
this.containerElementTypesCascadingMetaData = containerElementTypesCascadingMetaData;
this.cascading = cascading;
this.groupConversionHelper = groupConversionHelper;
this.hasContainerElementsMarkedForCascading = markedForCascadingOnContainerElements;
if ( TypeVariables.isAnnotatedObject( this.typeParameter ) || !markedForCascadingOnContainerElements ) {
this.valueExtractorCandidates = Collections.emptySet();
}
else {
this.valueExtractorCandidates = CollectionHelper.toImmutableSet(
valueExtractorManager.getResolver().getValueExtractorCandidatesForCascadedValidation( this.enclosingType, this.typeParameter )
);
if ( this.valueExtractorCandidates.size() == 0 ) {
throw LOG.getNoValueExtractorFoundForTypeException( this.declaredContainerClass, this.declaredTypeParameter );
}
}
}
ContainerCascadingMetaData(Type enclosingType, List containerElementTypesCascadingMetaData,
GroupConversionHelper groupConversionHelper, Set valueExtractorCandidates) {
this.enclosingType = enclosingType;
this.typeParameter = AnnotatedObject.INSTANCE;
this.declaredContainerClass = null;
this.declaredTypeParameter = null;
this.declaredTypeParameterIndex = null;
this.containerElementTypesCascadingMetaData = containerElementTypesCascadingMetaData;
this.cascading = true;
this.groupConversionHelper = groupConversionHelper;
this.hasContainerElementsMarkedForCascading = true;
this.valueExtractorCandidates = valueExtractorCandidates;
}
ContainerCascadingMetaData(Type enclosingType, TypeVariable typeParameter, Class declaredContainerClass, TypeVariable declaredTypeParameter,
GroupConversionHelper groupConversionHelper) {
this.enclosingType = enclosingType;
this.typeParameter = typeParameter;
this.declaredContainerClass = declaredContainerClass;
this.declaredTypeParameter = declaredTypeParameter;
this.declaredTypeParameterIndex = TypeVariables.getTypeParameterIndex( declaredTypeParameter );
this.containerElementTypesCascadingMetaData = Collections.emptyList();
this.cascading = true;
this.groupConversionHelper = groupConversionHelper;
this.hasContainerElementsMarkedForCascading = false;
this.valueExtractorCandidates = Collections.emptySet();
}
@Override
public boolean isContainer() {
return true;
}
@Override
public TypeVariable getTypeParameter() {
return typeParameter;
}
public Type getEnclosingType() {
return enclosingType;
}
public Class getDeclaredContainerClass() {
return declaredContainerClass;
}
public TypeVariable getDeclaredTypeParameter() {
return declaredTypeParameter;
}
public Integer getDeclaredTypeParameterIndex() {
return declaredTypeParameterIndex;
}
@Override
public boolean isCascading() {
return cascading;
}
public boolean hasContainerElementsMarkedForCascading() {
return hasContainerElementsMarkedForCascading;
}
@Override
public boolean isMarkedForCascadingOnAnnotatedObjectOrContainerElements() {
return cascading || hasContainerElementsMarkedForCascading;
}
public List getContainerElementTypesCascadingMetaData() {
return containerElementTypesCascadingMetaData;
}
@Override
public Class convertGroup(Class originalGroup) {
return groupConversionHelper.convertGroup( originalGroup );
}
@Override
public Set getGroupConversionDescriptors() {
return groupConversionHelper.asDescriptors();
}
@Override
@SuppressWarnings("unchecked")
public T as(Class clazz) {
if ( clazz.isAssignableFrom( getClass() ) ) {
return (T) this;
}
throw LOG.getUnableToCastException( this, clazz );
}
@Override
public CascadingMetaData addRuntimeContainerSupport(ValueExtractorManager valueExtractorManager, Class valueClass) {
return this;
}
public Set getValueExtractorCandidates() {
return valueExtractorCandidates;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append( getClass().getSimpleName() );
sb.append( " [" );
sb.append( "enclosingType=" ).append( StringHelper.toShortString( enclosingType ) ).append( ", " );
sb.append( "typeParameter=" ).append( typeParameter ).append( ", " );
sb.append( "cascading=" ).append( cascading ).append( ", " );
sb.append( "groupConversions=" ).append( groupConversionHelper ).append( ", " );
sb.append( "containerElementTypesCascadingMetaData=" ).append( containerElementTypesCascadingMetaData );
sb.append( "]" );
return sb.toString();
}
}