diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java
index 9c93a824d7..c33817137f 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java
@@ -604,7 +604,7 @@ public interface AvailableSettings {
public static final String INTERCEPTOR = "hibernate.sessionFactory.interceptor";
/**
- * Setting which defines the order (and therefore precedence) in whcih Hibernate will process mapping information.
+ * Setting which defines the order (and therefore precedence) in which Hibernate will process mapping information.
* Valid values include:
* - {@code hbm}
* - {@code class}
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/TypeSafeActivator.java b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/TypeSafeActivator.java
index b2bc5a143c..449d2d34ae 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/TypeSafeActivator.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/TypeSafeActivator.java
@@ -23,22 +23,18 @@
*/
package org.hibernate.cfg.beanvalidation;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
-import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import javax.validation.Validation;
import javax.validation.ValidatorFactory;
-import javax.validation.constraints.Digits;
-import javax.validation.constraints.Max;
-import javax.validation.constraints.Min;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Size;
import javax.validation.metadata.BeanDescriptor;
import javax.validation.metadata.ConstraintDescriptor;
import javax.validation.metadata.PropertyDescriptor;
@@ -48,17 +44,21 @@ import org.jboss.logging.Logger;
import org.hibernate.AssertionFailure;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
+import org.hibernate.cfg.beanvalidation.ddl.DigitsSchemaConstraint;
+import org.hibernate.cfg.beanvalidation.ddl.LengthSchemaConstraint;
+import org.hibernate.cfg.beanvalidation.ddl.MaxSchemaConstraint;
+import org.hibernate.cfg.beanvalidation.ddl.MinSchemaConstraint;
+import org.hibernate.cfg.beanvalidation.ddl.NotNullSchemaConstraint;
+import org.hibernate.cfg.beanvalidation.ddl.SchemaConstraint;
+import org.hibernate.cfg.beanvalidation.ddl.SizeSchemaConstraint;
import org.hibernate.dialect.Dialect;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventType;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.ReflectHelper;
-import org.hibernate.internal.util.StringHelper;
-import org.hibernate.mapping.Column;
import org.hibernate.mapping.Component;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
-import org.hibernate.mapping.SingleTableSubclass;
/**
* @author Emmanuel Bernard
@@ -66,13 +66,27 @@ import org.hibernate.mapping.SingleTableSubclass;
*/
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()
+ );
private static final String FACTORY_PROPERTY = "javax.persistence.validation.factory";
+ private static final List schemaConstraints;
+ private static final NotNullSchemaConstraint notNullSchemaConstraint = new NotNullSchemaConstraint();
- @SuppressWarnings( {"UnusedDeclaration"})
+ static {
+ schemaConstraints = new ArrayList();
+ schemaConstraints.add( new DigitsSchemaConstraint() );
+ schemaConstraints.add( new SizeSchemaConstraint() );
+ schemaConstraints.add( new MinSchemaConstraint() );
+ schemaConstraints.add( new MaxSchemaConstraint() );
+ schemaConstraints.add( new LengthSchemaConstraint() );
+ }
+
+ @SuppressWarnings({ "UnusedDeclaration" })
public static void validateFactory(Object object) {
- if ( ! ValidatorFactory.class.isInstance( object ) ) {
+ if ( !ValidatorFactory.class.isInstance( object ) ) {
throw new HibernateException(
"Given object was not an instance of " + ValidatorFactory.class.getName()
+ "[" + object.getClass().getName() + "]"
@@ -80,7 +94,7 @@ class TypeSafeActivator {
}
}
- @SuppressWarnings( {"UnusedDeclaration"})
+ @SuppressWarnings({ "UnusedDeclaration" })
public static void activateBeanValidation(EventListenerRegistry listenerRegistry, Properties properties) {
ValidatorFactory factory = getValidatorFactory( properties );
BeanValidationEventListener listener = new BeanValidationEventListener(
@@ -96,7 +110,7 @@ class TypeSafeActivator {
listener.initialize( properties );
}
- @SuppressWarnings( {"UnusedDeclaration"})
+ @SuppressWarnings({ "UnusedDeclaration" })
public static void applyDDL(Collection persistentClasses, Properties properties, Dialect dialect) {
ValidatorFactory factory = getValidatorFactory( properties );
Class>[] groupsArray = new GroupsPerOperation( properties ).get( GroupsPerOperation.Operation.DDL );
@@ -119,12 +133,93 @@ class TypeSafeActivator {
try {
applyDDL( "", persistentClass, clazz, factory, groups, true, dialect );
}
- catch (Exception e) {
+ catch ( Exception e ) {
LOG.unableToApplyConstraints( className, e );
}
}
}
+ private static void applyDDL(String prefix,
+ PersistentClass persistentClass,
+ Class> clazz,
+ ValidatorFactory factory,
+ Set> groups,
+ boolean activateNotNull,
+ Dialect dialect) {
+ final BeanDescriptor descriptor = factory.getValidator().getConstraintsForClass( clazz );
+ for ( PropertyDescriptor propertyDesc : descriptor.getConstrainedProperties() ) {
+ Property property = findPropertyByName( persistentClass, prefix + propertyDesc.getPropertyName() );
+ boolean hasNotNull;
+ if ( property != null ) {
+ hasNotNull = applyConstraints(
+ propertyDesc.getConstraintDescriptors(),
+ property,
+ propertyDesc,
+ groups,
+ activateNotNull,
+ dialect
+ );
+ if ( property.isComposite() && propertyDesc.isCascaded() ) {
+ Class> componentClass = ( ( Component ) property.getValue() ).getComponentClass();
+
+ /*
+ * we can apply not null if the upper component let's us activate not null
+ * and if the property is not null.
+ * Otherwise, all sub columns should be left nullable
+ */
+ final boolean canSetNotNullOnColumns = activateNotNull && hasNotNull;
+ applyDDL(
+ prefix + propertyDesc.getPropertyName() + ".",
+ persistentClass,
+ componentClass,
+ factory,
+ groups,
+ canSetNotNullOnColumns,
+ dialect
+ );
+ }
+ //FIXME add collection of components
+ }
+ }
+ }
+
+ private static boolean applyConstraints(Set> constraintDescriptors,
+ Property property,
+ PropertyDescriptor propertyDescriptor,
+ Set> groups,
+ boolean canApplyNotNull,
+ Dialect dialect
+ ) {
+ boolean hasNotNull = false;
+ for ( ConstraintDescriptor> constraintDescriptor : constraintDescriptors ) {
+ if ( groups != null && Collections.disjoint( constraintDescriptor.getGroups(), groups ) ) {
+ continue;
+ }
+
+ if ( canApplyNotNull ) {
+ hasNotNull = hasNotNull || notNullSchemaConstraint.applyConstraint(
+ property,
+ constraintDescriptor,
+ propertyDescriptor,
+ dialect
+ );
+ }
+
+ for ( SchemaConstraint schemaConstraint : schemaConstraints ) {
+ schemaConstraint.applyConstraint( property, constraintDescriptor, propertyDescriptor, dialect );
+ }
+
+ // pass an empty set as composing constraints inherit the main constraint and thus are matching already
+ hasNotNull = hasNotNull || applyConstraints(
+ constraintDescriptor.getComposingConstraints(),
+ property, propertyDescriptor, null,
+ canApplyNotNull,
+ dialect
+ );
+ }
+ return hasNotNull;
+ }
+
// public static void applyDDL( Iterable bindings,
// Properties properties,
// ClassLoaderService classLoaderService ) {
@@ -144,43 +239,6 @@ class TypeSafeActivator {
// }
// }
- private static void applyDDL(String prefix,
- PersistentClass persistentClass,
- Class> clazz,
- ValidatorFactory factory,
- Set> groups,
- boolean activateNotNull,
- Dialect dialect) {
- final BeanDescriptor descriptor = factory.getValidator().getConstraintsForClass( clazz );
- //no bean level constraints can be applied, go to the properties
-
- for ( PropertyDescriptor propertyDesc : descriptor.getConstrainedProperties() ) {
- Property property = findPropertyByName( persistentClass, prefix + propertyDesc.getPropertyName() );
- boolean hasNotNull;
- if ( property != null ) {
- hasNotNull = applyConstraints(
- propertyDesc.getConstraintDescriptors(), property, propertyDesc, groups, activateNotNull, dialect
- );
- if ( property.isComposite() && propertyDesc.isCascaded() ) {
- Class> componentClass = ( (Component) property.getValue() ).getComponentClass();
-
- /*
- * we can apply not null if the upper component let's us activate not null
- * and if the property is not null.
- * Otherwise, all sub columns should be left nullable
- */
- final boolean canSetNotNullOnColumns = activateNotNull && hasNotNull;
- applyDDL(
- prefix + propertyDesc.getPropertyName() + ".",
- persistentClass, componentClass, factory, groups,
- canSetNotNullOnColumns,
- dialect
- );
- }
- //FIXME add collection of components
- }
- }
- }
// private static void applyDDL( String prefix,
// EntityBinding binding,
@@ -199,45 +257,6 @@ class TypeSafeActivator {
// }
// }
- private static boolean applyConstraints(Set> constraintDescriptors,
- Property property,
- PropertyDescriptor propertyDesc,
- Set> groups,
- boolean canApplyNotNull,
- Dialect dialect
- ) {
- boolean hasNotNull = false;
- for ( ConstraintDescriptor> descriptor : constraintDescriptors ) {
- if ( groups != null && Collections.disjoint( descriptor.getGroups(), groups ) ) {
- continue;
- }
-
- if ( canApplyNotNull ) {
- hasNotNull = hasNotNull || applyNotNull( property, descriptor );
- }
-
- // apply bean validation specific constraints
- applyDigits( property, descriptor );
- applySize( property, descriptor, propertyDesc );
- applyMin( property, descriptor, dialect );
- applyMax( property, descriptor, dialect );
-
- // 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
- // will be taken care later
- applyLength( property, descriptor, propertyDesc );
-
- // pass an empty set as composing constraints inherit the main constraint and thus are matching already
- hasNotNull = hasNotNull || applyConstraints(
- descriptor.getComposingConstraints(),
- property, propertyDesc, null,
- canApplyNotNull,
- dialect
- );
- }
- return hasNotNull;
- }
-
// private static boolean applyConstraints( Set> constraintDescriptors,
// AttributeBinding attributeBinding,
// PropertyDescriptor propertyDesc,
@@ -269,58 +288,6 @@ class TypeSafeActivator {
// return hasNotNull;
// }
- private static void applyMin(Property property, ConstraintDescriptor> descriptor, Dialect dialect) {
- if ( Min.class.equals( descriptor.getAnnotation().annotationType() ) ) {
- @SuppressWarnings("unchecked")
- ConstraintDescriptor minConstraint = (ConstraintDescriptor) 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 maxConstraint = (ConstraintDescriptor) 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
- // multiple times
- if ( StringHelper.isNotEmpty( existingCheck ) && !existingCheck.contains( checkConstraint ) ) {
- checkConstraint = col.getCheckConstraint() + " AND " + checkConstraint;
- }
- col.setCheckConstraint( checkConstraint );
- }
-
- private static boolean applyNotNull(Property property, ConstraintDescriptor> descriptor) {
- boolean hasNotNull = false;
- if ( NotNull.class.equals( descriptor.getAnnotation().annotationType() ) ) {
- if ( !( property.getPersistentClass() instanceof SingleTableSubclass ) ) {
- //single table should not be forced to null
- if ( !property.isComposite() ) { //composite should not add not-null on all columns
- @SuppressWarnings( "unchecked" )
- Iterator iter = property.getColumnIterator();
- while ( iter.hasNext() ) {
- iter.next().setNullable( false );
- hasNotNull = true;
- }
- }
- }
- hasNotNull = true;
- }
- return hasNotNull;
- }
-
// private static boolean applyNotNull( AttributeBinding attributeBinding,
// ConstraintDescriptor> descriptor ) {
// boolean hasNotNull = false;
@@ -341,50 +308,14 @@ class TypeSafeActivator {
// return hasNotNull;
// }
- private static void applyDigits(Property property, ConstraintDescriptor> descriptor) {
- if ( Digits.class.equals( descriptor.getAnnotation().annotationType() ) ) {
- @SuppressWarnings("unchecked")
- ConstraintDescriptor digitsConstraint = (ConstraintDescriptor) descriptor;
- int integerDigits = digitsConstraint.getAnnotation().integer();
- int fractionalDigits = digitsConstraint.getAnnotation().fraction();
- Column col = (Column) property.getColumnIterator().next();
- col.setPrecision( integerDigits + fractionalDigits );
- col.setScale( fractionalDigits );
- }
- }
-
- private static void applySize(Property property, ConstraintDescriptor> descriptor, PropertyDescriptor propertyDescriptor) {
- if ( Size.class.equals( descriptor.getAnnotation().annotationType() )
- && String.class.equals( propertyDescriptor.getElementClass() ) ) {
- @SuppressWarnings("unchecked")
- ConstraintDescriptor sizeConstraint = (ConstraintDescriptor) descriptor;
- int max = sizeConstraint.getAnnotation().max();
- Column col = (Column) property.getColumnIterator().next();
- if ( max < Integer.MAX_VALUE ) {
- col.setLength( max );
- }
- }
- }
-
- private static void applyLength(Property property, ConstraintDescriptor> descriptor, PropertyDescriptor propertyDescriptor) {
- if ( "org.hibernate.validator.constraints.Length".equals(
- descriptor.getAnnotation().annotationType().getName()
- )
- && String.class.equals( propertyDescriptor.getElementClass() ) ) {
- @SuppressWarnings("unchecked")
- int max = (Integer) descriptor.getAttributes().get( "max" );
- Column col = (Column) property.getColumnIterator().next();
- if ( max < Integer.MAX_VALUE ) {
- col.setLength( max );
- }
- }
- }
-
/**
- * @param associatedClass
- * @param propertyName
- * @return the property by path in a recursive way, including IdentifierProperty in the loop if propertyName is
- * null
. If propertyName is null
or empty, the IdentifierProperty is returned
+ * Locates a mapping property of a persistent class by property name
+ *
+ * @param associatedClass the persistent class
+ * @param propertyName the property name
+ *
+ * @return the property by path in a recursive way, including IdentifierProperty in the loop if propertyName is
+ * null
. If propertyName is null
or empty, the IdentifierProperty is returned
*/
private static Property findPropertyByName(PersistentClass associatedClass, String propertyName) {
Property property = null;
@@ -404,7 +335,7 @@ class TypeSafeActivator {
}
StringTokenizer st = new StringTokenizer( propertyName, ".", false );
while ( st.hasMoreElements() ) {
- String element = (String) st.nextElement();
+ String element = ( String ) st.nextElement();
if ( property == null ) {
property = associatedClass.getProperty( element );
}
@@ -412,7 +343,7 @@ class TypeSafeActivator {
if ( !property.isComposite() ) {
return null;
}
- property = ( (Component) property.getValue() ).getProperty( element );
+ property = ( ( Component ) property.getValue() ).getProperty( element );
}
}
}
@@ -425,7 +356,7 @@ class TypeSafeActivator {
}
StringTokenizer st = new StringTokenizer( propertyName, ".", false );
while ( st.hasMoreElements() ) {
- String element = (String) st.nextElement();
+ String element = ( String ) st.nextElement();
if ( property == null ) {
property = associatedClass.getIdentifierMapper().getProperty( element );
}
@@ -433,7 +364,7 @@ class TypeSafeActivator {
if ( !property.isComposite() ) {
return null;
}
- property = ( (Component) property.getValue() ).getProperty( element );
+ property = ( ( Component ) property.getValue() ).getProperty( element );
}
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/ddl/DigitsSchemaConstraint.java b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/ddl/DigitsSchemaConstraint.java
new file mode 100644
index 0000000000..f2aace438e
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/ddl/DigitsSchemaConstraint.java
@@ -0,0 +1,55 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2012, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.cfg.beanvalidation.ddl;
+
+import javax.validation.constraints.Digits;
+import javax.validation.metadata.ConstraintDescriptor;
+import javax.validation.metadata.PropertyDescriptor;
+
+import org.hibernate.dialect.Dialect;
+import org.hibernate.mapping.Column;
+import org.hibernate.mapping.Property;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class DigitsSchemaConstraint implements SchemaConstraint {
+ @Override
+ public boolean applyConstraint(Property property, ConstraintDescriptor> descriptor, PropertyDescriptor propertyDescriptor, Dialect dialect) {
+ if ( !Digits.class.equals( descriptor.getAnnotation().annotationType() ) ) {
+ return false;
+ }
+
+ @SuppressWarnings("unchecked")
+ ConstraintDescriptor digitsConstraint = ( ConstraintDescriptor ) descriptor;
+ int integerDigits = digitsConstraint.getAnnotation().integer();
+ int fractionalDigits = digitsConstraint.getAnnotation().fraction();
+ Column col = ( Column ) property.getColumnIterator().next();
+ col.setPrecision( integerDigits + fractionalDigits );
+ col.setScale( fractionalDigits );
+ return true;
+ }
+}
+
+
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/ddl/LengthSchemaConstraint.java b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/ddl/LengthSchemaConstraint.java
new file mode 100644
index 0000000000..7a5e713f31
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/ddl/LengthSchemaConstraint.java
@@ -0,0 +1,59 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2012, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.cfg.beanvalidation.ddl;
+
+import javax.validation.metadata.ConstraintDescriptor;
+import javax.validation.metadata.PropertyDescriptor;
+
+import org.hibernate.dialect.Dialect;
+import org.hibernate.mapping.Column;
+import org.hibernate.mapping.Property;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class LengthSchemaConstraint implements SchemaConstraint {
+ // 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
+ // will be taken care later
+ private static final String LENGTH_CONSTRAINT = "org.hibernate.validator.constraints.Length";
+
+ @Override
+ public boolean applyConstraint(Property property, ConstraintDescriptor> descriptor, PropertyDescriptor propertyDescriptor, Dialect dialect) {
+ if ( !LENGTH_CONSTRAINT.equals( descriptor.getAnnotation().annotationType().getName() )
+ || !String.class.equals( propertyDescriptor.getElementClass() ) ) {
+ return false;
+ }
+
+ @SuppressWarnings("unchecked")
+ int max = ( Integer ) descriptor.getAttributes().get( "max" );
+ Column col = ( Column ) property.getColumnIterator().next();
+ if ( max < Integer.MAX_VALUE ) {
+ col.setLength( max );
+ }
+ return true;
+ }
+}
+
+
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/ddl/MaxSchemaConstraint.java b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/ddl/MaxSchemaConstraint.java
new file mode 100644
index 0000000000..e97dfc8ee6
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/ddl/MaxSchemaConstraint.java
@@ -0,0 +1,52 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2012, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.cfg.beanvalidation.ddl;
+
+import javax.validation.constraints.Max;
+import javax.validation.metadata.ConstraintDescriptor;
+import javax.validation.metadata.PropertyDescriptor;
+
+import org.hibernate.dialect.Dialect;
+import org.hibernate.mapping.Column;
+import org.hibernate.mapping.Property;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class MaxSchemaConstraint implements SchemaConstraint {
+ @Override
+ public boolean applyConstraint(Property property, ConstraintDescriptor> descriptor, PropertyDescriptor propertyDescriptor, Dialect dialect) {
+ if ( !Max.class.equals( descriptor.getAnnotation().annotationType() ) ) {
+ return false;
+ }
+
+ @SuppressWarnings("unchecked")
+ ConstraintDescriptor maxConstraint = ( ConstraintDescriptor ) descriptor;
+ long max = maxConstraint.getAnnotation().value();
+ Column col = ( Column ) property.getColumnIterator().next();
+ String checkConstraint = col.getQuotedName( dialect ) + "<=" + max;
+ SchemaModificationHelper.applySQLCheck( col, checkConstraint );
+ return true;
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/ddl/MinSchemaConstraint.java b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/ddl/MinSchemaConstraint.java
new file mode 100644
index 0000000000..f1e7d07c8b
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/ddl/MinSchemaConstraint.java
@@ -0,0 +1,57 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2012, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.cfg.beanvalidation.ddl;
+
+import javax.validation.constraints.Min;
+import javax.validation.metadata.ConstraintDescriptor;
+import javax.validation.metadata.PropertyDescriptor;
+
+import org.hibernate.dialect.Dialect;
+import org.hibernate.mapping.Column;
+import org.hibernate.mapping.Property;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class MinSchemaConstraint implements SchemaConstraint {
+ @Override
+ public boolean applyConstraint(Property property, ConstraintDescriptor> descriptor, PropertyDescriptor propertyDescriptor, Dialect dialect) {
+ if ( !Min.class.equals( descriptor.getAnnotation().annotationType() ) ) {
+ return false;
+ }
+
+ @SuppressWarnings("unchecked")
+ ConstraintDescriptor minConstraint = ( ConstraintDescriptor ) descriptor;
+ long min = minConstraint.getAnnotation().value();
+
+ Column col = ( Column ) property.getColumnIterator().next();
+ String checkConstraint = col.getQuotedName( dialect ) + ">=" + min;
+ SchemaModificationHelper.applySQLCheck( col, checkConstraint );
+ return true;
+
+
+ }
+}
+
+
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/ddl/NotNullSchemaConstraint.java b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/ddl/NotNullSchemaConstraint.java
new file mode 100644
index 0000000000..038f896dc7
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/ddl/NotNullSchemaConstraint.java
@@ -0,0 +1,60 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2012, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.cfg.beanvalidation.ddl;
+
+import java.util.Iterator;
+import javax.validation.constraints.NotNull;
+import javax.validation.metadata.ConstraintDescriptor;
+import javax.validation.metadata.PropertyDescriptor;
+
+import org.hibernate.dialect.Dialect;
+import org.hibernate.mapping.Column;
+import org.hibernate.mapping.Property;
+import org.hibernate.mapping.SingleTableSubclass;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class NotNullSchemaConstraint implements SchemaConstraint {
+ @Override
+ public boolean applyConstraint(Property property, ConstraintDescriptor> descriptor, PropertyDescriptor propertyDescriptor, Dialect dialect) {
+ if ( !NotNull.class.equals( descriptor.getAnnotation().annotationType() ) ) {
+ return false;
+ }
+
+ if ( !( property.getPersistentClass() instanceof SingleTableSubclass ) ) {
+ //single table should not be forced to null
+ if ( !property.isComposite() ) { //composite should not add not-null on all columns
+ @SuppressWarnings("unchecked")
+ Iterator iter = property.getColumnIterator();
+ while ( iter.hasNext() ) {
+ iter.next().setNullable( false );
+
+ }
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/ddl/SchemaConstraint.java b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/ddl/SchemaConstraint.java
new file mode 100644
index 0000000000..abf4fde069
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/ddl/SchemaConstraint.java
@@ -0,0 +1,41 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2012, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.cfg.beanvalidation.ddl;
+
+import javax.validation.metadata.ConstraintDescriptor;
+import javax.validation.metadata.PropertyDescriptor;
+
+import org.hibernate.dialect.Dialect;
+import org.hibernate.mapping.Property;
+
+/**
+ * Interface for modification of schema related meta information based on Bean Validation constraints
+ *
+ * @author Hardy Ferentschik
+ */
+public interface SchemaConstraint {
+ boolean applyConstraint(Property property, ConstraintDescriptor> descriptor, PropertyDescriptor propertyDescriptor, Dialect dialect);
+}
+
+
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/ddl/SchemaModificationHelper.java b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/ddl/SchemaModificationHelper.java
new file mode 100644
index 0000000000..7d963d80a2
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/ddl/SchemaModificationHelper.java
@@ -0,0 +1,47 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2012, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.cfg.beanvalidation.ddl;
+
+import org.hibernate.internal.util.StringHelper;
+import org.hibernate.mapping.Column;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class SchemaModificationHelper {
+ private SchemaModificationHelper() {
+ }
+
+ public 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
+ // multiple times
+ if ( StringHelper.isNotEmpty( existingCheck ) && !existingCheck.contains( checkConstraint ) ) {
+ checkConstraint = col.getCheckConstraint() + " AND " + checkConstraint;
+ }
+ col.setCheckConstraint( checkConstraint );
+ }
+}
+
+
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/ddl/SizeSchemaConstraint.java b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/ddl/SizeSchemaConstraint.java
new file mode 100644
index 0000000000..e4e0dc1529
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/ddl/SizeSchemaConstraint.java
@@ -0,0 +1,56 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2012, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.cfg.beanvalidation.ddl;
+
+import javax.validation.constraints.Size;
+import javax.validation.metadata.ConstraintDescriptor;
+import javax.validation.metadata.PropertyDescriptor;
+
+import org.hibernate.dialect.Dialect;
+import org.hibernate.mapping.Column;
+import org.hibernate.mapping.Property;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class SizeSchemaConstraint implements SchemaConstraint {
+ @Override
+ public boolean applyConstraint(Property property, ConstraintDescriptor> descriptor, PropertyDescriptor propertyDescriptor, Dialect dialect) {
+ if ( !Size.class.equals( descriptor.getAnnotation().annotationType() )
+ || !String.class.equals( propertyDescriptor.getElementClass() ) ) {
+ return false;
+ }
+
+ @SuppressWarnings("unchecked")
+ ConstraintDescriptor sizeConstraint = ( ConstraintDescriptor ) descriptor;
+ int max = sizeConstraint.getAnnotation().max();
+ Column col = ( Column ) property.getColumnIterator().next();
+ if ( max < Integer.MAX_VALUE ) {
+ col.setLength( max );
+ }
+ return true;
+ }
+}
+
+