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

Hibernate example source code file (Nullability.java)

This example Hibernate source code file (Nullability.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

collectiontype, compositetype, compositetype, entitypersister, hibernateexception, iterator, nullability, object, object, propertyvalueexception, string, string, type, type, util

The Hibernate Nullability.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.engine.internal;

import java.util.Iterator;

import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.PropertyValueException;
import org.hibernate.bytecode.instrumentation.spi.LazyPropertyInitializer;
import org.hibernate.engine.spi.CascadingAction;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.CollectionType;
import org.hibernate.type.CompositeType;
import org.hibernate.type.Type;

/**
 * Implements the algorithm for validating property values for illegal null values
 * 
 * @author Gavin King
 */
public final class Nullability {
	
	private final SessionImplementor session;
	private final boolean checkNullability;

	public Nullability(SessionImplementor session) {
		this.session = session;
		this.checkNullability = session.getFactory().getSettings().isCheckNullability();
	}
	/**
	 * Check nullability of the class persister properties
	 *
	 * @param values entity properties
	 * @param persister class persister
	 * @param isUpdate whether 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
	 */
	public void checkNullability(
			final Object[] values,
			final EntityPersister persister,
			final boolean isUpdate) 
	throws PropertyValueException, HibernateException {
		/*
		 * Typically when Bean Validation is on, we don't want to validate null values
		 * at the Hibernate Core level. Hence the checkNullability setting.
		 */
		if ( checkNullability ) {
			/*
			  * 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 )
							);
						}

					}
				}

			}
		}
	}

	/**
	 * 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
	 */
	private String checkSubElementsNullability(final Type propertyType, final Object value) 
	throws HibernateException {
		//for non null args, check for components and elements containing components
		if ( propertyType.isComponentType() ) {
			return checkComponentNullability( value, (CompositeType) 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

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

	/**
	 * 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
	 */
	private String checkComponentNullability(final Object value, final CompositeType compType)
	throws HibernateException {
		/* 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, EntityMode.POJO );
			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;
	}

	/**
	 * Return a well formed property path.
	 * Basically, it will return parent.child
	 *
	 * @param parent parent in path
	 * @param child child in path
	 * @return parent-child path
	 */
	private static String buildPropertyPath(String parent, String child) {
		return new StringBuilder( parent.length() + child.length() + 1 )
			.append(parent).append('.').append(child).toString();
	}

}

Other Hibernate examples (source code examples)

Here is a short list of links related to this Hibernate Nullability.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.