org.hibernate.validator.internal.xml.MetaConstraintBuilder 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.xml;
import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
import javax.validation.Payload;
import javax.validation.ValidationException;
import javax.xml.bind.JAXBElement;
import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager;
import org.hibernate.validator.internal.metadata.core.ConstraintHelper;
import org.hibernate.validator.internal.metadata.core.MetaConstraint;
import org.hibernate.validator.internal.metadata.core.MetaConstraints;
import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl;
import org.hibernate.validator.internal.metadata.location.ConstraintLocation;
import org.hibernate.validator.internal.util.TypeResolutionHelper;
import org.hibernate.validator.internal.util.annotation.AnnotationDescriptor;
import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor;
import org.hibernate.validator.internal.util.logging.Log;
import org.hibernate.validator.internal.util.logging.LoggerFactory;
import org.hibernate.validator.internal.util.privilegedactions.GetMethod;
import org.hibernate.validator.internal.xml.binding.AnnotationType;
import org.hibernate.validator.internal.xml.binding.ConstraintType;
import org.hibernate.validator.internal.xml.binding.ElementType;
import org.hibernate.validator.internal.xml.binding.GroupsType;
import org.hibernate.validator.internal.xml.binding.PayloadType;
/**
* Build meta constraint from XML
*
* @author Hardy Ferentschik
*/
class MetaConstraintBuilder {
private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() );
private static final Pattern IS_ONLY_WHITESPACE = Pattern.compile( "\\s*" );
private static final Class[] EMPTY_CLASSES_ARRAY = new Class[0];
private final ClassLoadingHelper classLoadingHelper;
private final ConstraintHelper constraintHelper;
private final TypeResolutionHelper typeResolutionHelper;
private final ValueExtractorManager valueExtractorManager;
MetaConstraintBuilder(ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper,
ValueExtractorManager valueExtractorManager) {
this.classLoadingHelper = classLoadingHelper;
this.constraintHelper = constraintHelper;
this.typeResolutionHelper = typeResolutionHelper;
this.valueExtractorManager = valueExtractorManager;
}
@SuppressWarnings("unchecked")
MetaConstraint buildMetaConstraint(ConstraintLocation constraintLocation,
ConstraintType constraint,
java.lang.annotation.ElementType type,
String defaultPackage,
ConstraintDescriptorImpl.ConstraintType constraintType) {
Class annotationClass;
try {
annotationClass = (Class) classLoadingHelper.loadClass( constraint.getAnnotation(), defaultPackage );
}
catch (ValidationException e) {
throw LOG.getUnableToLoadConstraintAnnotationClassException( constraint.getAnnotation(), e );
}
ConstraintAnnotationDescriptor.Builder annotationDescriptorBuilder = new ConstraintAnnotationDescriptor.Builder<>( annotationClass );
if ( constraint.getMessage() != null ) {
annotationDescriptorBuilder.setMessage( constraint.getMessage() );
}
annotationDescriptorBuilder.setGroups( getGroups( constraint.getGroups(), defaultPackage ) )
.setPayload( getPayload( constraint.getPayload(), defaultPackage ) );
for ( ElementType elementType : constraint.getElement() ) {
String name = elementType.getName();
checkNameIsValid( name );
Class returnType = getAnnotationParameterType( annotationClass, name );
Object elementValue = getElementValue( elementType, returnType, defaultPackage );
annotationDescriptorBuilder.setAttribute( name, elementValue );
}
ConstraintAnnotationDescriptor annotationDescriptor;
try {
annotationDescriptor = annotationDescriptorBuilder.build();
}
catch (RuntimeException e) {
throw LOG.getUnableToCreateAnnotationForConfiguredConstraintException( e );
}
// we set initially ConstraintOrigin.DEFINED_LOCALLY for all xml configured constraints
// later we will make copies of this constraint descriptor when needed and adjust the ConstraintOrigin
ConstraintDescriptorImpl constraintDescriptor = new ConstraintDescriptorImpl(
constraintHelper, constraintLocation.getMember(), annotationDescriptor, type, constraintType
);
return MetaConstraints.create( typeResolutionHelper, valueExtractorManager, constraintDescriptor, constraintLocation );
}
private Annotation buildAnnotation(AnnotationType annotationType, Class returnType, String defaultPackage) {
AnnotationDescriptor.Builder annotationDescriptorBuilder = new AnnotationDescriptor.Builder<>( returnType );
for ( ElementType elementType : annotationType.getElement() ) {
String name = elementType.getName();
Class parameterType = getAnnotationParameterType( returnType, name );
Object elementValue = getElementValue( elementType, parameterType, defaultPackage );
annotationDescriptorBuilder.setAttribute( name, elementValue );
}
return annotationDescriptorBuilder.build().getAnnotation();
}
private static void checkNameIsValid(String name) {
if ( ConstraintHelper.MESSAGE.equals( name ) || ConstraintHelper.GROUPS.equals( name ) ) {
throw LOG.getReservedParameterNamesException( ConstraintHelper.MESSAGE, ConstraintHelper.GROUPS, ConstraintHelper.PAYLOAD );
}
}
private static Class getAnnotationParameterType(Class annotationClass, String name) {
Method m = run( GetMethod.action( annotationClass, name ) );
if ( m == null ) {
throw LOG.getAnnotationDoesNotContainAParameterException( annotationClass, name );
}
return m.getReturnType();
}
private Object getElementValue(ElementType elementType, Class returnType, String defaultPackage) {
removeEmptyContentElements( elementType );
boolean isArray = returnType.isArray();
if ( !isArray ) {
if ( elementType.getContent().size() == 0 ) {
if ( returnType == String.class ) {
return "";
}
else {
throw LOG.getEmptyElementOnlySupportedWhenCharSequenceIsExpectedExpection();
}
}
else if ( elementType.getContent().size() > 1 ) {
throw LOG.getAttemptToSpecifyAnArrayWhereSingleValueIsExpectedException();
}
return getSingleValue( elementType.getContent().get( 0 ), returnType, defaultPackage );
}
else {
List