alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Hibernate example source code file (TypeSafeActivator.java)

This example Hibernate source code file (TypeSafeActivator.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Hibernate tags/keywords

class, column, column, constraintdescriptor, constraintdescriptor, property, propertydescriptor, set, string, string, stringtokenizer, suppresswarnings, suppresswarnings, util, validatorfactory

The Hibernate TypeSafeActivator.java source code

/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * Copyright (c) 2010, 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;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
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;
import org.hibernate.AssertionFailure;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.cfg.Configuration;
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;
import org.jboss.logging.Logger;

/**
 * @author Emmanuel Bernard
 * @author Hardy Ferentschik
 */
class TypeSafeActivator {

    private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, TypeSafeActivator.class.getName());

	private static final String FACTORY_PROPERTY = "javax.persistence.validation.factory";

	@SuppressWarnings( {"UnusedDeclaration"})
	public static void validateFactory(Object object) {
		if ( ! ValidatorFactory.class.isInstance( object ) ) {
			throw new HibernateException(
					"Given object was not an instance of " + ValidatorFactory.class.getName()
							+ "[" + object.getClass().getName() + "]"
			);
		}
	}

	@SuppressWarnings( {"UnusedDeclaration"})
	public static void activateBeanValidation(EventListenerRegistry listenerRegistry, Configuration configuration) {
		final Properties properties = configuration.getProperties();
		ValidatorFactory factory = getValidatorFactory( properties );
		BeanValidationEventListener listener = new BeanValidationEventListener(
				factory, properties
		);

		listenerRegistry.addDuplicationStrategy( DuplicationStrategyImpl.INSTANCE );

		listenerRegistry.appendListeners( EventType.PRE_INSERT, listener );
		listenerRegistry.appendListeners( EventType.PRE_UPDATE, listener );
		listenerRegistry.appendListeners( EventType.PRE_DELETE, listener );

		listener.initialize( configuration );
	}

//    public static void activateBeanValidation( EventListenerRegistry listenerRegistry ) {
//        final Properties properties = configuration.getProperties();
//        ValidatorFactory factory = getValidatorFactory( properties );
//        BeanValidationEventListener listener = new BeanValidationEventListener(
//                factory, properties
//        );
//
//        listenerRegistry.addDuplicationStrategy( DuplicationStrategyImpl.INSTANCE );
//
//        listenerRegistry.appendListeners( EventType.PRE_INSERT, listener );
//        listenerRegistry.appendListeners( EventType.PRE_UPDATE, listener );
//        listenerRegistry.appendListeners( EventType.PRE_DELETE, listener );
//
//        listener.initialize( configuration );
//    }

	@SuppressWarnings( {"UnusedDeclaration"})
	public static void applyDDL(Collection<PersistentClass> persistentClasses, Properties properties) {
		ValidatorFactory factory = getValidatorFactory( properties );
		Class<?>[] groupsArray = new GroupsPerOperation( properties ).get( GroupsPerOperation.Operation.DDL );
		Set<Class groups = new HashSet>( Arrays.asList( groupsArray ) );

		for ( PersistentClass persistentClass : persistentClasses ) {
			final String className = persistentClass.getClassName();

			if ( className == null || className.length() == 0 ) {
				continue;
			}
			Class<?> clazz;
			try {
				clazz = ReflectHelper.classForName( className, TypeSafeActivator.class );
			}
			catch ( ClassNotFoundException e ) {
				throw new AssertionFailure( "Entity class not found", e );
			}

			try {
				applyDDL( "", persistentClass, clazz, factory, groups, true );
			}
			catch (Exception e) {
                LOG.unableToApplyConstraints(className, e);
			}
		}
	}

//    public static void applyDDL( Iterable<EntityBinding> bindings,
//                                 Properties properties,
//                                 ClassLoaderService classLoaderService ) {
//        ValidatorFactory factory = getValidatorFactory(properties);
//        Class<?>[] groupsArray = new GroupsPerOperation(properties).get(GroupsPerOperation.Operation.DDL);
//        Set<Class groups = new HashSet>(Arrays.asList(groupsArray));
//        for (EntityBinding binding : bindings) {
//            final String className = binding.getEntity().getClassName();
//            if (className == null || className.length() == 0) continue;
//            try {
//                applyDDL("", binding, classLoaderService.classForName(className), factory, groups, true);
//            } catch (ClassLoadingException error) {
//                throw new AssertionFailure("Entity class not found", error);
//            } catch (Exception error) {
//                LOG.unableToApplyConstraints(className, error);
//            }
//        }
//    }

	private static void applyDDL(String prefix,
								 PersistentClass persistentClass,
								 Class<?> clazz,
								 ValidatorFactory factory,
								 Set<Class groups,
								 boolean activateNotNull) {
		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
				);
				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
					);
				}
				//FIXME add collection of components
			}
		}
	}

//    private static void applyDDL( String prefix,
//                                  EntityBinding binding,
//                                  Class<?> clazz,
//                                  ValidatorFactory factory,
//                                  Set<Class groups,
//                                  boolean activateNotNull ) {
//        final BeanDescriptor descriptor = factory.getValidator().getConstraintsForClass(clazz);
//        //no bean level constraints can be applied, go to the properties
//        for (PropertyDescriptor propertyDesc : descriptor.getConstrainedProperties()) {
//            AttributeBinding attrBinding = findAttributeBindingByName(binding, prefix + propertyDesc.getPropertyName());
//            if (attrBinding != null) {
//                applyConstraints(propertyDesc.getConstraintDescriptors(), attrBinding, propertyDesc, groups, activateNotNull);
//                // TODO: Handle composite attributes when possible
//            }
//        }
//    }

	private static boolean applyConstraints(Set<ConstraintDescriptor constraintDescriptors,
											Property property,
											PropertyDescriptor propertyDesc,
											Set<Class groups,
											boolean canApplyNotNull
	) {
		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 );
			applyMax( property, descriptor );

			// 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
			);
		}
		return hasNotNull;
	}

//    private static boolean applyConstraints( Set<ConstraintDescriptor constraintDescriptors,
//                                             AttributeBinding attributeBinding,
//                                             PropertyDescriptor propertyDesc,
//                                             Set<Class groups,
//                                             boolean canApplyNotNull ) {
//        boolean hasNotNull = false;
//        for ( ConstraintDescriptor<?> descriptor : constraintDescriptors ) {
//            if (groups != null && Collections.disjoint(descriptor.getGroups(), groups)) continue;
//            if (canApplyNotNull) hasNotNull = hasNotNull || applyNotNull(attributeBinding, descriptor);
//
//            // apply bean validation specific constraints
//            applyDigits( property, descriptor );
//            applySize( property, descriptor, propertyDesc );
//            applyMin( property, descriptor );
//            applyMax( property, descriptor );
//
//            // 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
//            );
//        }
//        return hasNotNull;
//    }

	private static void applyMin(Property property, ConstraintDescriptor<?> descriptor) {
		if ( Min.class.equals( descriptor.getAnnotation().annotationType() ) ) {
			@SuppressWarnings("unchecked")
			ConstraintDescriptor<Min> minConstraint = (ConstraintDescriptor) descriptor;
			long min = minConstraint.getAnnotation().value();

			Column col = (Column) property.getColumnIterator().next();
			String checkConstraint = col.getName() + ">=" + min;
			applySQLCheck( col, checkConstraint );
		}
	}

	private static void applyMax(Property property, ConstraintDescriptor<?> descriptor) {
		if ( Max.class.equals( descriptor.getAnnotation().annotationType() ) ) {
			@SuppressWarnings("unchecked")
			ConstraintDescriptor<Max> maxConstraint = (ConstraintDescriptor) descriptor;
			long max = maxConstraint.getAnnotation().value();
			Column col = (Column) property.getColumnIterator().next();
			String checkConstraint = col.getName() + "<=" + 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<Column> 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;
//        if (NotNull.class.equals(descriptor.getAnnotation().annotationType())) {
//            if ( !( attributeBinding.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<Column> iter = property.getColumnIterator();
//                    while ( iter.hasNext() ) {
//                        iter.next().setNullable( false );
//                        hasNotNull = true;
//                    }
//                }
//            }
//            hasNotNull = true;
//        }
//        return hasNotNull;
//    }

	private static void applyDigits(Property property, ConstraintDescriptor<?> descriptor) {
		if ( Digits.class.equals( descriptor.getAnnotation().annotationType() ) ) {
			@SuppressWarnings("unchecked")
			ConstraintDescriptor<Digits> 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<Size> 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
     * <code>null.  If propertyName is null or empty, the IdentifierProperty is returned
	 */
	private static Property findPropertyByName(PersistentClass associatedClass, String propertyName) {
		Property property = null;
		Property idProperty = associatedClass.getIdentifierProperty();
		String idName = idProperty != null ? idProperty.getName() : null;
		try {
			if ( propertyName == null
					|| propertyName.length() == 0
					|| propertyName.equals( idName ) ) {
				//default to id
				property = idProperty;
			}
			else {
				if ( propertyName.indexOf( idName + "." ) == 0 ) {
					property = idProperty;
					propertyName = propertyName.substring( idName.length() + 1 );
				}
				StringTokenizer st = new StringTokenizer( propertyName, ".", false );
				while ( st.hasMoreElements() ) {
					String element = (String) st.nextElement();
					if ( property == null ) {
						property = associatedClass.getProperty( element );
					}
					else {
						if ( !property.isComposite() ) {
							return null;
						}
						property = ( (Component) property.getValue() ).getProperty( element );
					}
				}
			}
		}
		catch ( MappingException e ) {
			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;
	}

//    /**
//     * @param entityBinding
//     * @param attrName
//     * @return the attribute by path in a recursive way, including EntityIdentifier in the loop if attrName is
//     * <code>null.  If attrName is null or empty, the EntityIdentifier is returned
//     */
//    private static AttributeBinding findAttributeBindingByName( EntityBinding entityBinding,
//                                                                String attrName ) {
//        AttributeBinding attrBinding = null;
//        EntityIdentifier identifier = entityBinding.getHierarchyDetails().getEntityIdentifier();
//        BasicAttributeBinding idAttrBinding = identifier.getValueBinding();
//        String idAttrName = idAttrBinding != null ? idAttrBinding.getAttribute().getName() : null;
//        try {
//            if (attrName == null || attrName.length() == 0 || attrName.equals(idAttrName)) attrBinding = idAttrBinding; // default to id
//            else {
//                if (attrName.indexOf(idAttrName + ".") == 0) {
//                    attrBinding = idAttrBinding;
//                    attrName = attrName.substring(idAttrName.length() + 1);
//                }
//                for (StringTokenizer st = new StringTokenizer(attrName, "."); st.hasMoreElements();) {
//                    String element = st.nextToken();
//                    if (attrBinding == null) attrBinding = entityBinding.locateAttributeBinding(element);
//                    else return null; // TODO: if (attrBinding.isComposite()) ...
//                }
//            }
//        } catch (MappingException error) {
//            try {
//                //if we do not find it try to check the identifier mapper
//                if (!identifier.isIdentifierMapper()) return null;
//                // TODO: finish once composite/embedded/component IDs get worked out
//            }
//            catch ( MappingException ee ) {
//                return null;
//            }
//        }
//        return attrBinding;
//    }

	private static ValidatorFactory getValidatorFactory(Map<Object, Object> properties) {
		ValidatorFactory factory = null;
		if ( properties != null ) {
			Object unsafeProperty = properties.get( FACTORY_PROPERTY );
			if ( unsafeProperty != null ) {
				try {
					factory = ValidatorFactory.class.cast( unsafeProperty );
				}
				catch ( ClassCastException e ) {
					throw new HibernateException(
							"Property " + FACTORY_PROPERTY
									+ " should contain an object of type " + ValidatorFactory.class.getName()
					);
				}
			}
		}
		if ( factory == null ) {
			try {
				factory = Validation.buildDefaultValidatorFactory();
			}
			catch ( Exception e ) {
				throw new HibernateException( "Unable to build the default ValidatorFactory", e );
			}
		}
		return factory;
	}
}

Other Hibernate examples (source code examples)

Here is a short list of links related to this Hibernate TypeSafeActivator.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.