FileDocCategorySizeDatePackage
Nullability.javaAPI DocHibernate 3.2.56177Wed Jul 20 02:16:34 BST 2005org.hibernate.engine

Nullability

public final class Nullability extends Object
Implements the algorithm for validating property values for illegal null values
author
Gavin King

Fields Summary
private final SessionImplementor
session
Constructors Summary
public Nullability(SessionImplementor session)

		this.session = session;
	
Methods Summary
private static java.lang.StringbuildPropertyPath(java.lang.String parent, java.lang.String child)
Return a well formed property path. Basicaly, it will return parent.child

param
parent parent in path
param
child child in path
return
parent-child path

		return new StringBuffer( parent.length() + child.length() + 1 )
			.append(parent).append('.").append(child).toString();
	
private java.lang.StringcheckComponentNullability(java.lang.Object value, org.hibernate.type.AbstractComponentType compType)
check component nullability. Returns property path that break nullability or null if none

param
value component properties
param
compType component not-nullable type
return
property path
throws
HibernateException error while getting subcomponent values

		/* will check current level if some of them are not null
		 * or sublevels if they exist
		 */
		boolean[] nullability = compType.getPropertyNullability();
		if ( nullability!=null ) {
			//do the test
			final Object[] values = compType.getPropertyValues( value, session.getEntityMode() );
			final Type[] propertyTypes = compType.getSubtypes();
			for ( int i=0; i<values.length; i++ ) {
				final Object subvalue = values[i];
				if ( !nullability[i] && subvalue==null ) {
					return compType.getPropertyNames()[i];
				}
				else if ( subvalue != null ) {
					String breakProperties = checkSubElementsNullability( propertyTypes[i], subvalue );
					if ( breakProperties != null ) {
						return buildPropertyPath( compType.getPropertyNames()[i], breakProperties );
					}
	 			}
	 		}
		}
		return null;
	
public voidcheckNullability(java.lang.Object[] values, org.hibernate.persister.entity.EntityPersister persister, boolean isUpdate)
Check nullability of the class persister properties

param
values entity properties
param
persister class persister
param
isUpdate wether it is intended to be updated or saved
throws
org.hibernate.PropertyValueException Break the nullability of one property
throws
HibernateException error while getting Component values


		/*
		  * Algorithm
		  * Check for any level one nullability breaks
		  * Look at non null components to
		  *   recursively check next level of nullability breaks
		  * Look at Collections contraining component to
		  *   recursively check next level of nullability breaks
		  *
		  *
		  * In the previous implementation, not-null stuffs where checked
		  * filtering by level one only updateable
		  * or insertable columns. So setting a sub component as update="false"
		  * has no effect on not-null check if the main component had good checkeability
		  * In this implementation, we keep this feature.
		  * However, I never see any documentation mentioning that, but it's for
		  * sure a limitation.
		  */

		final boolean[] nullability = persister.getPropertyNullability();
		final boolean[] checkability = isUpdate ?
			persister.getPropertyUpdateability() :
			persister.getPropertyInsertability();
		final Type[] propertyTypes = persister.getPropertyTypes();

		for ( int i = 0; i < values.length; i++ ) {
			
			if ( checkability[i] && values[i]!=LazyPropertyInitializer.UNFETCHED_PROPERTY ) {
				final Object value = values[i];
				if ( !nullability[i] && value == null ) {
					
					//check basic level one nullablilty
					throw new PropertyValueException(
							"not-null property references a null or transient value",
							persister.getEntityName(),
							persister.getPropertyNames()[i]
						);
					
				}
				else if ( value != null ) {
					
					//values is not null and is checkable, we'll look deeper
					String breakProperties = checkSubElementsNullability( propertyTypes[i], value );
					if ( breakProperties != null ) {
						throw new PropertyValueException(
							"not-null property references a null or transient value",
							persister.getEntityName(),
							buildPropertyPath( persister.getPropertyNames()[i], breakProperties )
						);
					}
					
				}
			}
			
		}
	
private java.lang.StringcheckSubElementsNullability(org.hibernate.type.Type propertyType, java.lang.Object value)
check sub elements-nullability. Returns property path that break nullability or null if none

param
propertyType type to check
param
value value to check
return
property path
throws
HibernateException error while getting subcomponent values

		//for non null args, check for components and elements containing components
		if ( propertyType.isComponentType() ) {
			return checkComponentNullability( value, (AbstractComponentType) propertyType );
		}
		else if ( propertyType.isCollectionType() ) {

			//persistent collections may have components
			CollectionType collectionType = (CollectionType) propertyType;
			Type collectionElementType = collectionType.getElementType( session.getFactory() );
			if ( collectionElementType.isComponentType() ) {
				//check for all components values in the collection

				AbstractComponentType componentType = (AbstractComponentType) collectionElementType;
				Iterator iter = CascadingAction.getLoadedElementsIterator(session, collectionType, value);
				while ( iter.hasNext() ) {
					Object compValue = iter.next();
					if (compValue != null) {
						return checkComponentNullability(compValue, componentType);
					}
				}
			}
		}
		return null;