mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-08 04:08:19 +00:00
HHH-8960 First cut of re-enabled BV integration
This commit is contained in:
parent
c46dbebc5b
commit
bf611d4e18
@ -26,7 +26,7 @@
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
@ -41,8 +41,9 @@
|
|||||||
import javax.validation.metadata.ConstraintDescriptor;
|
import javax.validation.metadata.ConstraintDescriptor;
|
||||||
import javax.validation.metadata.PropertyDescriptor;
|
import javax.validation.metadata.PropertyDescriptor;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
import org.hibernate.AssertionFailure;
|
import org.hibernate.AssertionFailure;
|
||||||
import org.hibernate.MappingException;
|
|
||||||
import org.hibernate.cfg.Environment;
|
import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||||
@ -52,16 +53,17 @@
|
|||||||
import org.hibernate.internal.util.ReflectHelper;
|
import org.hibernate.internal.util.ReflectHelper;
|
||||||
import org.hibernate.internal.util.StringHelper;
|
import org.hibernate.internal.util.StringHelper;
|
||||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||||
import org.hibernate.mapping.Column;
|
import org.hibernate.metamodel.spi.binding.AbstractSingularAssociationAttributeBinding;
|
||||||
import org.hibernate.mapping.Property;
|
import org.hibernate.metamodel.spi.binding.AbstractSingularAttributeBinding;
|
||||||
import org.hibernate.mapping.Selectable;
|
|
||||||
import org.hibernate.mapping.SingleTableSubclass;
|
|
||||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||||
|
import org.hibernate.metamodel.spi.binding.BasicAttributeBinding;
|
||||||
|
import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding;
|
||||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||||
|
import org.hibernate.metamodel.spi.binding.InheritanceType;
|
||||||
|
import org.hibernate.metamodel.spi.binding.RelationalValueBinding;
|
||||||
import org.hibernate.metamodel.spi.domain.Attribute;
|
import org.hibernate.metamodel.spi.domain.Attribute;
|
||||||
import org.hibernate.metamodel.spi.domain.SingularAttribute;
|
import org.hibernate.metamodel.spi.domain.SingularAttribute;
|
||||||
|
import org.hibernate.metamodel.spi.relational.Column;
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Emmanuel Bernard
|
* @author Emmanuel Bernard
|
||||||
@ -70,16 +72,19 @@
|
|||||||
*/
|
*/
|
||||||
class TypeSafeActivator {
|
class TypeSafeActivator {
|
||||||
|
|
||||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, TypeSafeActivator.class.getName());
|
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||||
|
CoreMessageLogger.class,
|
||||||
|
TypeSafeActivator.class.getName()
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to validate a supplied ValidatorFactory instance as being castable to ValidatorFactory.
|
* Used to validate a supplied ValidatorFactory instance as being castable to ValidatorFactory.
|
||||||
*
|
*
|
||||||
* @param object The supplied ValidatorFactory instance.
|
* @param object The supplied ValidatorFactory instance.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings( {"UnusedDeclaration"})
|
@SuppressWarnings({ "UnusedDeclaration" })
|
||||||
public static void validateSuppliedFactory(Object object) {
|
public static void validateSuppliedFactory(Object object) {
|
||||||
if ( ! ValidatorFactory.class.isInstance( object ) ) {
|
if ( !ValidatorFactory.class.isInstance( object ) ) {
|
||||||
throw new IntegrationException(
|
throw new IntegrationException(
|
||||||
"Given object was not an instance of " + ValidatorFactory.class.getName()
|
"Given object was not an instance of " + ValidatorFactory.class.getName()
|
||||||
+ "[" + object.getClass().getName() + "]"
|
+ "[" + object.getClass().getName() + "]"
|
||||||
@ -94,12 +99,18 @@ public static void activate(ActivationContext activationContext) {
|
|||||||
try {
|
try {
|
||||||
factory = getValidatorFactory( activationContext );
|
factory = getValidatorFactory( activationContext );
|
||||||
}
|
}
|
||||||
catch (IntegrationException e) {
|
catch ( IntegrationException e ) {
|
||||||
if ( activationContext.getValidationModes().contains( ValidationMode.CALLBACK ) ) {
|
if ( activationContext.getValidationModes().contains( ValidationMode.CALLBACK ) ) {
|
||||||
throw new IntegrationException( "Bean Validation provider was not available, but 'callback' validation was requested", e );
|
throw new IntegrationException(
|
||||||
|
"Bean Validation provider was not available, but 'callback' validation was requested",
|
||||||
|
e
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if ( activationContext.getValidationModes().contains( ValidationMode.DDL ) ) {
|
if ( activationContext.getValidationModes().contains( ValidationMode.DDL ) ) {
|
||||||
throw new IntegrationException( "Bean Validation provider was not available, but 'ddl' validation was requested", e );
|
throw new IntegrationException(
|
||||||
|
"Bean Validation provider was not available, but 'ddl' validation was requested",
|
||||||
|
e
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG.debug( "Unable to acquire Bean Validation ValidatorFactory, skipping activation" );
|
LOG.debug( "Unable to acquire Bean Validation ValidatorFactory, skipping activation" );
|
||||||
@ -111,10 +122,10 @@ public static void activate(ActivationContext activationContext) {
|
|||||||
applyCallbackListeners( factory, activationContext );
|
applyCallbackListeners( factory, activationContext );
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings( {"UnusedDeclaration"})
|
@SuppressWarnings({ "UnusedDeclaration" })
|
||||||
public static void applyCallbackListeners(ValidatorFactory validatorFactory, ActivationContext activationContext) {
|
public static void applyCallbackListeners(ValidatorFactory validatorFactory, ActivationContext activationContext) {
|
||||||
final Set<ValidationMode> modes = activationContext.getValidationModes();
|
final Set<ValidationMode> modes = activationContext.getValidationModes();
|
||||||
if ( ! ( modes.contains( ValidationMode.CALLBACK ) || modes.contains( ValidationMode.AUTO ) ) ) {
|
if ( !( modes.contains( ValidationMode.CALLBACK ) || modes.contains( ValidationMode.AUTO ) ) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,16 +152,15 @@ public static void applyCallbackListeners(ValidatorFactory validatorFactory, Act
|
|||||||
listener.initialize( activationContext.getSettings() );
|
listener.initialize( activationContext.getSettings() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({"unchecked", "UnusedParameters"})
|
|
||||||
private static void applyRelationalConstraints(ValidatorFactory factory, ActivationContext activationContext) {
|
private static void applyRelationalConstraints(ValidatorFactory factory, ActivationContext activationContext) {
|
||||||
final Map properties = activationContext.getSettings();
|
final Map properties = activationContext.getSettings();
|
||||||
if ( ! ConfigurationHelper.getBoolean( BeanValidationIntegrator.APPLY_CONSTRAINTS, properties, true ) ){
|
if ( !ConfigurationHelper.getBoolean( BeanValidationIntegrator.APPLY_CONSTRAINTS, properties, true ) ) {
|
||||||
LOG.debug( "Skipping application of relational constraints from legacy Hibernate Validator" );
|
LOG.debug( "Skipping application of relational constraints from legacy Hibernate Validator" );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Set<ValidationMode> modes = activationContext.getValidationModes();
|
final Set<ValidationMode> modes = activationContext.getValidationModes();
|
||||||
if ( ! ( modes.contains( ValidationMode.DDL ) || modes.contains( ValidationMode.AUTO ) ) ) {
|
if ( !( modes.contains( ValidationMode.DDL ) || modes.contains( ValidationMode.AUTO ) ) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,8 +169,6 @@ private static void applyRelationalConstraints(ValidatorFactory factory, Activat
|
|||||||
Class<?>[] groupsArray = new GroupsPerOperation( properties ).get( GroupsPerOperation.Operation.DDL );
|
Class<?>[] groupsArray = new GroupsPerOperation( properties ).get( GroupsPerOperation.Operation.DDL );
|
||||||
Set<Class<?>> groups = new HashSet<Class<?>>( Arrays.asList( groupsArray ) );
|
Set<Class<?>> groups = new HashSet<Class<?>>( Arrays.asList( groupsArray ) );
|
||||||
|
|
||||||
// Hardy : I started working on this as part of a big metamodel clean up I am doing, but this got to be too
|
|
||||||
// much of a rabbit hole. - Steve
|
|
||||||
for ( EntityBinding entityBinding : activationContext.getMetadata().getEntityBindings() ) {
|
for ( EntityBinding entityBinding : activationContext.getMetadata().getEntityBindings() ) {
|
||||||
final String className = entityBinding.getEntity().getClassReference().getName();
|
final String className = entityBinding.getEntity().getClassReference().getName();
|
||||||
|
|
||||||
@ -178,7 +186,7 @@ private static void applyRelationalConstraints(ValidatorFactory factory, Activat
|
|||||||
try {
|
try {
|
||||||
applyDDL( "", entityBinding, clazz, factory, groups, true, dialect );
|
applyDDL( "", entityBinding, clazz, factory, groups, true, dialect );
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch ( Exception e ) {
|
||||||
LOG.unableToApplyConstraints( className, e );
|
LOG.unableToApplyConstraints( className, e );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -193,43 +201,45 @@ private static void applyDDL(
|
|||||||
boolean activateNotNull,
|
boolean activateNotNull,
|
||||||
Dialect dialect) {
|
Dialect dialect) {
|
||||||
final BeanDescriptor descriptor = factory.getValidator().getConstraintsForClass( clazz );
|
final BeanDescriptor descriptor = factory.getValidator().getConstraintsForClass( clazz );
|
||||||
//no bean level constraints can be applied, go to the properties
|
|
||||||
|
|
||||||
for ( PropertyDescriptor propertyDesc : descriptor.getConstrainedProperties() ) {
|
// no bean level constraints can be applied, just iterate the properties
|
||||||
|
for ( PropertyDescriptor propertyDescriptor : descriptor.getConstrainedProperties() ) {
|
||||||
AttributeBinding attributeBinding = findPropertyByName(
|
AttributeBinding attributeBinding = findPropertyByName(
|
||||||
entityBinding,
|
entityBinding,
|
||||||
prefix + propertyDesc.getPropertyName()
|
prefix + propertyDescriptor.getPropertyName()
|
||||||
);
|
);
|
||||||
boolean hasNotNull;
|
if ( attributeBinding == null ) {
|
||||||
if ( attributeBinding != null ) {
|
continue;
|
||||||
hasNotNull = applyConstraints(
|
}
|
||||||
propertyDesc.getConstraintDescriptors(),
|
|
||||||
attributeBinding,
|
|
||||||
propertyDesc,
|
|
||||||
groups,
|
|
||||||
activateNotNull,
|
|
||||||
dialect
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( propertyDesc.isCascaded() ) {
|
boolean hasNotNull;
|
||||||
// if it is a composite, visit its attributes
|
hasNotNull = applyConstraints(
|
||||||
final Attribute attribute = attributeBinding.getAttribute();
|
propertyDescriptor.getConstraintDescriptors(),
|
||||||
if ( attribute.isSingular() ) {
|
attributeBinding,
|
||||||
final SingularAttribute singularAttribute = (SingularAttribute) attribute;
|
propertyDescriptor,
|
||||||
if ( singularAttribute.getSingularAttributeType().isAggregate() ) {
|
groups,
|
||||||
final Class componentClass =
|
activateNotNull,
|
||||||
singularAttribute.getSingularAttributeType().getClassReference().getResolvedClass();
|
dialect
|
||||||
final boolean canSetNotNullOnColumns = activateNotNull && hasNotNull;
|
);
|
||||||
applyDDL(
|
|
||||||
prefix + propertyDesc.getPropertyName() + ".",
|
if ( propertyDescriptor.isCascaded() ) {
|
||||||
entityBinding,
|
// if it is a composite, visit its attributes
|
||||||
componentClass,
|
final Attribute attribute = attributeBinding.getAttribute();
|
||||||
factory,
|
if ( attribute.isSingular() ) {
|
||||||
groups,
|
final SingularAttribute singularAttribute = (SingularAttribute) attribute;
|
||||||
canSetNotNullOnColumns,
|
if ( singularAttribute.getSingularAttributeType().isAggregate() ) {
|
||||||
dialect
|
final Class<?> componentClass = singularAttribute.getSingularAttributeType()
|
||||||
);
|
.getClassReference().getResolvedClass();
|
||||||
}
|
final boolean canSetNotNullOnColumns = activateNotNull && hasNotNull;
|
||||||
|
applyDDL(
|
||||||
|
prefix + propertyDescriptor.getPropertyName() + ".",
|
||||||
|
entityBinding,
|
||||||
|
componentClass,
|
||||||
|
factory,
|
||||||
|
groups,
|
||||||
|
canSetNotNullOnColumns,
|
||||||
|
dialect
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -238,8 +248,8 @@ private static void applyDDL(
|
|||||||
|
|
||||||
private static boolean applyConstraints(
|
private static boolean applyConstraints(
|
||||||
Set<ConstraintDescriptor<?>> constraintDescriptors,
|
Set<ConstraintDescriptor<?>> constraintDescriptors,
|
||||||
AttributeBinding property,
|
AttributeBinding attributeBinding,
|
||||||
PropertyDescriptor propertyDesc,
|
PropertyDescriptor propertyDescriptor,
|
||||||
Set<Class<?>> groups,
|
Set<Class<?>> groups,
|
||||||
boolean canApplyNotNull,
|
boolean canApplyNotNull,
|
||||||
Dialect dialect) {
|
Dialect dialect) {
|
||||||
@ -249,197 +259,184 @@ private static boolean applyConstraints(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo : Hardy - here are the rabbit holes...
|
if ( canApplyNotNull ) {
|
||||||
// first...
|
hasNotNull = hasNotNull || applyNotNull( attributeBinding, descriptor );
|
||||||
// if ( canApplyNotNull ) {
|
}
|
||||||
// hasNotNull = hasNotNull || applyNotNull( property, descriptor );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// apply bean validation specific constraints
|
// apply bean validation specific constraints
|
||||||
// second...
|
applyDigits( attributeBinding, descriptor );
|
||||||
// applyDigits( property, descriptor );
|
applySize( attributeBinding, descriptor, propertyDescriptor );
|
||||||
// applySize( property, descriptor, propertyDesc );
|
applyMin( attributeBinding, descriptor, dialect );
|
||||||
// applyMin( property, descriptor, dialect );
|
applyMax( attributeBinding, descriptor, dialect );
|
||||||
// applyMax( property, descriptor, dialect );
|
|
||||||
|
|
||||||
// apply hibernate validator specific constraints - we cannot import any HV specific classes though!
|
// apply hibernate validator specific constraints - we cannot import any HV specific classes though!
|
||||||
// no need to check explicitly for @Range. @Range is a composed constraint using @Min and @Max which
|
// no need to check explicitly for @Range. @Range is a composed constraint using @Min and @Max which
|
||||||
// will be taken care later
|
// will be taken care later
|
||||||
// third
|
applyLength( attributeBinding, descriptor );
|
||||||
// applyLength( property, descriptor, propertyDesc );
|
|
||||||
|
|
||||||
// pass an empty set as composing constraints inherit the main constraint and thus are matching already
|
// pass an empty set as composing constraints inherit the main constraint and thus are matching already
|
||||||
hasNotNull = hasNotNull || applyConstraints(
|
hasNotNull = hasNotNull || applyConstraints(
|
||||||
descriptor.getComposingConstraints(),
|
descriptor.getComposingConstraints(),
|
||||||
property, propertyDesc, null,
|
attributeBinding, propertyDescriptor, null,
|
||||||
canApplyNotNull,
|
canApplyNotNull,
|
||||||
dialect
|
dialect
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return hasNotNull;
|
return hasNotNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void applyMin(Property property, ConstraintDescriptor<?> descriptor, Dialect dialect) {
|
private static void applySQLCheck(Column column, String checkConstraint) {
|
||||||
if ( Min.class.equals( descriptor.getAnnotation().annotationType() ) ) {
|
String existingCheck = column.getCheckCondition();
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
ConstraintDescriptor<Min> minConstraint = (ConstraintDescriptor<Min>) descriptor;
|
|
||||||
long min = minConstraint.getAnnotation().value();
|
|
||||||
|
|
||||||
Column col = (Column) property.getColumnIterator().next();
|
|
||||||
String checkConstraint = col.getQuotedName(dialect) + ">=" + min;
|
|
||||||
applySQLCheck( col, checkConstraint );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void applyMax(Property property, ConstraintDescriptor<?> descriptor, Dialect dialect) {
|
|
||||||
if ( Max.class.equals( descriptor.getAnnotation().annotationType() ) ) {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
ConstraintDescriptor<Max> maxConstraint = (ConstraintDescriptor<Max>) descriptor;
|
|
||||||
long max = maxConstraint.getAnnotation().value();
|
|
||||||
Column col = (Column) property.getColumnIterator().next();
|
|
||||||
String checkConstraint = col.getQuotedName(dialect) + "<=" + max;
|
|
||||||
applySQLCheck( col, checkConstraint );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void applySQLCheck(Column col, String checkConstraint) {
|
|
||||||
String existingCheck = col.getCheckConstraint();
|
|
||||||
// need to check whether the new check is already part of the existing check, because applyDDL can be called
|
// need to check whether the new check is already part of the existing check, because applyDDL can be called
|
||||||
// multiple times
|
// multiple times
|
||||||
if ( StringHelper.isNotEmpty( existingCheck ) && !existingCheck.contains( checkConstraint ) ) {
|
if ( StringHelper.isNotEmpty( existingCheck ) && !existingCheck.contains( checkConstraint ) ) {
|
||||||
checkConstraint = col.getCheckConstraint() + " AND " + checkConstraint;
|
checkConstraint = column.getCheckCondition() + " AND " + checkConstraint;
|
||||||
}
|
}
|
||||||
col.setCheckConstraint( checkConstraint );
|
column.setCheckCondition( checkConstraint );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean applyNotNull(Property property, ConstraintDescriptor<?> descriptor) {
|
private static boolean applyNotNull(AttributeBinding attributeBinding, ConstraintDescriptor<?> descriptor) {
|
||||||
boolean hasNotNull = false;
|
if ( !NotNull.class.equals( descriptor.getAnnotation().annotationType() ) ) {
|
||||||
if ( NotNull.class.equals( descriptor.getAnnotation().annotationType() ) ) {
|
return false;
|
||||||
// single table inheritance should not be forced to null due to shared state
|
|
||||||
if ( !( property.getPersistentClass() instanceof SingleTableSubclass ) ) {
|
|
||||||
//composite should not add not-null on all columns
|
|
||||||
if ( !property.isComposite() ) {
|
|
||||||
final Iterator<Selectable> iter = property.getColumnIterator();
|
|
||||||
while ( iter.hasNext() ) {
|
|
||||||
final Selectable selectable = iter.next();
|
|
||||||
if ( Column.class.isInstance( selectable ) ) {
|
|
||||||
Column.class.cast( selectable ).setNullable( false );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LOG.debugf(
|
|
||||||
"@NotNull was applied to attribute [%s] which is defined (at least partially) " +
|
|
||||||
"by formula(s); formula portions will be skipped",
|
|
||||||
property.getName()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
hasNotNull = true;
|
|
||||||
}
|
}
|
||||||
return hasNotNull;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void applyDigits(Property property, ConstraintDescriptor<?> descriptor) {
|
if ( InheritanceType.SINGLE_TABLE.equals(
|
||||||
if ( Digits.class.equals( descriptor.getAnnotation().annotationType() ) ) {
|
attributeBinding.getContainer()
|
||||||
@SuppressWarnings("unchecked")
|
.seekEntityBinding()
|
||||||
ConstraintDescriptor<Digits> digitsConstraint = (ConstraintDescriptor<Digits>) descriptor;
|
.getHierarchyDetails()
|
||||||
int integerDigits = digitsConstraint.getAnnotation().integer();
|
.getInheritanceType()
|
||||||
int fractionalDigits = digitsConstraint.getAnnotation().fraction();
|
) ) {
|
||||||
Column col = (Column) property.getColumnIterator().next();
|
return false;
|
||||||
col.setPrecision( integerDigits + fractionalDigits );
|
|
||||||
col.setScale( fractionalDigits );
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static void applySize(Property property, ConstraintDescriptor<?> descriptor, PropertyDescriptor propertyDescriptor) {
|
List<RelationalValueBinding> relationalValueBindings = Collections.emptyList();
|
||||||
if ( Size.class.equals( descriptor.getAnnotation().annotationType() )
|
if ( attributeBinding instanceof BasicAttributeBinding ) {
|
||||||
&& String.class.equals( propertyDescriptor.getElementClass() ) ) {
|
BasicAttributeBinding basicBinding = (BasicAttributeBinding) attributeBinding;
|
||||||
@SuppressWarnings("unchecked")
|
relationalValueBindings = basicBinding.getRelationalValueBindings();
|
||||||
ConstraintDescriptor<Size> sizeConstraint = (ConstraintDescriptor<Size>) descriptor;
|
}
|
||||||
int max = sizeConstraint.getAnnotation().max();
|
|
||||||
Column col = (Column) property.getColumnIterator().next();
|
if ( attributeBinding instanceof AbstractSingularAssociationAttributeBinding ) {
|
||||||
if ( max < Integer.MAX_VALUE ) {
|
AbstractSingularAssociationAttributeBinding singularAttributeBinding = (AbstractSingularAssociationAttributeBinding) attributeBinding;
|
||||||
col.setLength( max );
|
relationalValueBindings = singularAttributeBinding.getRelationalValueBindings();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( attributeBinding instanceof AbstractSingularAttributeBinding ) {
|
||||||
|
AbstractSingularAttributeBinding singularAttributeBinding = (AbstractSingularAttributeBinding) attributeBinding;
|
||||||
|
relationalValueBindings = singularAttributeBinding.getRelationalValueBindings();
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( RelationalValueBinding relationalValueBinding : relationalValueBindings ) {
|
||||||
|
if ( relationalValueBinding.getValue() instanceof Column ) {
|
||||||
|
Column column = (Column) relationalValueBinding.getValue();
|
||||||
|
column.setNullable( false );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void applyLength(Property property, ConstraintDescriptor<?> descriptor, PropertyDescriptor propertyDescriptor) {
|
private static void applyMin(AttributeBinding attributeBinding, ConstraintDescriptor<?> descriptor, Dialect dialect) {
|
||||||
if ( "org.hibernate.validator.constraints.Length".equals(
|
if ( !Min.class.equals( descriptor.getAnnotation().annotationType() ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
long min = (Long) descriptor.getAttributes().get( "value" );
|
||||||
|
Column column = getSingleColumn( attributeBinding );
|
||||||
|
String checkConstraint = column.getColumnName().getText( dialect ) + ">=" + min;
|
||||||
|
applySQLCheck( column, checkConstraint );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void applyMax(AttributeBinding attributeBinding, ConstraintDescriptor<?> descriptor, Dialect dialect) {
|
||||||
|
if ( !Max.class.equals( descriptor.getAnnotation().annotationType() ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
long max = (Long) descriptor.getAttributes().get( "value" );
|
||||||
|
Column column = getSingleColumn( attributeBinding );
|
||||||
|
String checkConstraint = column.getColumnName().getText( dialect ) + "<=" + max;
|
||||||
|
applySQLCheck( column, checkConstraint );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void applySize(AttributeBinding attributeBinding, ConstraintDescriptor<?> descriptor, PropertyDescriptor propertyDescriptor) {
|
||||||
|
if ( !( Size.class.equals( descriptor.getAnnotation().annotationType() )
|
||||||
|
&& String.class.equals( propertyDescriptor.getElementClass() ) ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int max = (Integer) descriptor.getAttributes().get( "max" );
|
||||||
|
Column column = getSingleColumn( attributeBinding );
|
||||||
|
if ( max < Integer.MAX_VALUE ) {
|
||||||
|
column.setSize( org.hibernate.metamodel.spi.relational.Size.length( max ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void applyLength(AttributeBinding attributeBinding, ConstraintDescriptor<?> descriptor) {
|
||||||
|
if ( !"org.hibernate.validator.constraints.Length".equals(
|
||||||
descriptor.getAnnotation().annotationType().getName()
|
descriptor.getAnnotation().annotationType().getName()
|
||||||
)
|
) ) {
|
||||||
&& String.class.equals( propertyDescriptor.getElementClass() ) ) {
|
return;
|
||||||
@SuppressWarnings("unchecked")
|
}
|
||||||
int max = (Integer) descriptor.getAttributes().get( "max" );
|
|
||||||
Column col = (Column) property.getColumnIterator().next();
|
int max = (Integer) descriptor.getAttributes().get( "max" );
|
||||||
if ( max < Integer.MAX_VALUE ) {
|
Column column = getSingleColumn( attributeBinding );
|
||||||
col.setLength( max );
|
if ( max < Integer.MAX_VALUE ) {
|
||||||
}
|
column.setSize( org.hibernate.metamodel.spi.relational.Size.length( max ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AttributeBinding findPropertyByName(EntityBinding entityBinding, String propertyName) {
|
private static void applyDigits(AttributeBinding attributeBinding, ConstraintDescriptor<?> descriptor) {
|
||||||
// Returns the property by path in a recursive way, including IdentifierProperty in the loop
|
if ( !Digits.class.equals( descriptor.getAnnotation().annotationType() ) ) {
|
||||||
// if propertyName is null. If propertyName is null or empty, the IdentifierProperty is returned
|
return;
|
||||||
final AttributeBinding idAttributeBinding = entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding();
|
}
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
ConstraintDescriptor<Digits> digitsConstraint = (ConstraintDescriptor<Digits>) descriptor;
|
||||||
|
int integerDigits = digitsConstraint.getAnnotation().integer();
|
||||||
|
int fractionalDigits = digitsConstraint.getAnnotation().fraction();
|
||||||
|
|
||||||
|
Column column = getSingleColumn( attributeBinding );
|
||||||
|
org.hibernate.metamodel.spi.relational.Size size = org.hibernate.metamodel.spi.relational.Size.precision(
|
||||||
|
integerDigits + fractionalDigits,
|
||||||
|
fractionalDigits
|
||||||
|
);
|
||||||
|
column.setSize( size );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@code AttributeBinding} for the attribute/property specified by given path.
|
||||||
|
*
|
||||||
|
* @param entityBinding the root entity binding from which to start the search for the property
|
||||||
|
* @param propertyPath the property path
|
||||||
|
*
|
||||||
|
* @return Returns the {@code AttributeBinding} for the attribute/property specified by given path. If
|
||||||
|
* {@code propertyPath} is {@code null} or empty, the id attribute binding is returned.
|
||||||
|
*/
|
||||||
|
private static AttributeBinding findPropertyByName(EntityBinding entityBinding, String propertyPath) {
|
||||||
|
final AttributeBinding idAttributeBinding = entityBinding.getHierarchyDetails()
|
||||||
|
.getEntityIdentifier()
|
||||||
|
.getAttributeBinding();
|
||||||
final String idAttributeName = idAttributeBinding == null ? null : idAttributeBinding.getAttribute().getName();
|
final String idAttributeName = idAttributeBinding == null ? null : idAttributeBinding.getAttribute().getName();
|
||||||
|
|
||||||
AttributeBinding property = null;
|
if ( propertyPath == null || propertyPath.length() == 0 || propertyPath.equals( idAttributeName ) ) {
|
||||||
try {
|
//default to id
|
||||||
if ( propertyName == null
|
return idAttributeBinding;
|
||||||
|| propertyName.length() == 0
|
}
|
||||||
|| propertyName.equals( idAttributeName ) ) {
|
|
||||||
//default to id
|
AttributeBinding attributeBinding = null;
|
||||||
property = idAttributeBinding;
|
StringTokenizer tokenizer = new StringTokenizer( propertyPath, ".", false );
|
||||||
|
while ( tokenizer.hasMoreElements() ) {
|
||||||
|
String element = (String) tokenizer.nextElement();
|
||||||
|
if ( attributeBinding == null ) {
|
||||||
|
attributeBinding = entityBinding.locateAttributeBinding( element );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ( propertyName.indexOf( idAttributeName + "." ) == 0 ) {
|
if ( !isComposite( attributeBinding ) ) {
|
||||||
property = idAttributeBinding;
|
return null;
|
||||||
propertyName = propertyName.substring( idAttributeName.length() + 1 );
|
|
||||||
}
|
|
||||||
StringTokenizer st = new StringTokenizer( propertyName, ".", false );
|
|
||||||
while ( st.hasMoreElements() ) {
|
|
||||||
String element = (String) st.nextElement();
|
|
||||||
if ( property == null ) {
|
|
||||||
property = entityBinding.locateAttributeBinding( element );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if ( !isComposite( property ) ) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// todo : Hardy - not sure exactly what to do here...
|
|
||||||
//property = ( (Component) property.getValue() ).getProperty( element );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
CompositeAttributeBinding compositeAttributeBinding = (CompositeAttributeBinding) attributeBinding;
|
||||||
|
attributeBinding = compositeAttributeBinding.locateAttributeBinding( element );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch ( MappingException e ) {
|
return attributeBinding;
|
||||||
// todo : Hardy - nor here...
|
|
||||||
// try {
|
|
||||||
// //if we do not find it try to check the identifier mapper
|
|
||||||
// if ( associatedClass.getIdentifierMapper() == null ) {
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
// StringTokenizer st = new StringTokenizer( propertyName, ".", false );
|
|
||||||
// while ( st.hasMoreElements() ) {
|
|
||||||
// String element = (String) st.nextElement();
|
|
||||||
// if ( property == null ) {
|
|
||||||
// property = associatedClass.getIdentifierMapper().getProperty( element );
|
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
// if ( !property.isComposite() ) {
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
// property = ( (Component) property.getValue() ).getProperty( element );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// catch ( MappingException ee ) {
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
return property;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isComposite(AttributeBinding property) {
|
private static boolean isComposite(AttributeBinding property) {
|
||||||
@ -453,7 +450,9 @@ private static boolean isComposite(AttributeBinding property) {
|
|||||||
|
|
||||||
private static ValidatorFactory getValidatorFactory(ActivationContext activationContext) {
|
private static ValidatorFactory getValidatorFactory(ActivationContext activationContext) {
|
||||||
// first look for an explicitly passed ValidatorFactory
|
// first look for an explicitly passed ValidatorFactory
|
||||||
final Object reference = activationContext.getSessionFactory().getSessionFactoryOptions().getValidatorFactoryReference();
|
final Object reference = activationContext.getSessionFactory()
|
||||||
|
.getSessionFactoryOptions()
|
||||||
|
.getValidatorFactoryReference();
|
||||||
if ( reference != null ) {
|
if ( reference != null ) {
|
||||||
try {
|
try {
|
||||||
return ValidatorFactory.class.cast( reference );
|
return ValidatorFactory.class.cast( reference );
|
||||||
@ -473,4 +472,21 @@ private static ValidatorFactory getValidatorFactory(ActivationContext activation
|
|||||||
throw new IntegrationException( "Unable to build the default ValidatorFactory", e );
|
throw new IntegrationException( "Unable to build the default ValidatorFactory", e );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Column getSingleColumn(AttributeBinding attributeBinding) {
|
||||||
|
BasicAttributeBinding basicBinding = (BasicAttributeBinding) attributeBinding;
|
||||||
|
List<RelationalValueBinding> relationalValueBindings = basicBinding.getRelationalValueBindings();
|
||||||
|
if ( relationalValueBindings.size() > 1 ) {
|
||||||
|
throw new IntegrationException(
|
||||||
|
"Unexpected number of relational columns for attribute "
|
||||||
|
+ attributeBinding.getAttribute().getName()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
for ( RelationalValueBinding relationalValueBinding : relationalValueBindings ) {
|
||||||
|
if ( relationalValueBinding.getValue() instanceof Column ) {
|
||||||
|
return (Column) relationalValueBinding.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user