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

Hibernate example source code file (MetadataContext.java)

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

entitytypeimpl, entitytypeimpl, hashmap, iterator, map, map, mappedsuperclasstypeimpl, persistentclass, persistentclass, property, reflection, set, suppresswarnings, util, x, x

The Hibernate MetadataContext.java source code

/*
 * Copyright (c) 2009, Red Hat Middleware LLC 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 Middleware LLC.
 *
 * 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.ejb.metamodel;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.IdentifiableType;
import javax.persistence.metamodel.SingularAttribute;
import org.hibernate.annotations.common.AssertionFailure;
import org.hibernate.ejb.internal.EntityManagerMessageLogger;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.mapping.Component;
import org.hibernate.mapping.KeyValue;
import org.hibernate.mapping.MappedSuperclass;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.jboss.logging.Logger;

/**
 * Defines a context for storing information during the building of the {@link MetamodelImpl}.
 * <p/>
 * This contextual information includes data needing to be processed in a second pass as well as
 * cross-references into the built metamodel classes.
 * <p/>
 * At the end of the day, clients are interested in the {@link #getEntityTypeMap} and {@link #getEmbeddableTypeMap}
 * results, which represent all the registered {@linkplain #registerEntityType entities} and
 *  {@linkplain #registerEmbeddedableType embeddables} respectively.
 *
 * @author Steve Ebersole
 * @author Emmanuel Bernard
 */
class MetadataContext {

    private static final EntityManagerMessageLogger LOG = Logger.getMessageLogger(EntityManagerMessageLogger.class,
                                                                           MetadataContext.class.getName());

	private final SessionFactoryImplementor sessionFactory;
	private final AttributeFactory attributeFactory = new AttributeFactory( this );

	private Map<Class> entityTypes
			= new HashMap<Class>();
	private Map<String,EntityTypeImpl entityTypesByEntityName
			= new HashMap<String, EntityTypeImpl();
	private Map<PersistentClass,EntityTypeImpl entityTypesByPersistentClass
			= new HashMap<PersistentClass,EntityTypeImpl();
	private Map<Class> embeddables
			= new HashMap<Class>();
	private Map<MappedSuperclass, MappedSuperclassTypeImpl mappedSuperclassByMappedSuperclassMapping
			= new HashMap<MappedSuperclass,MappedSuperclassTypeImpl();
	//this list contains MappedSuperclass and EntityTypes ordered by superclass first
	private List<Object> orderedMappings = new ArrayList();
	/**
	 * Stack of PersistentClass being process. Last in the list is the highest in the stack.
	 *
	 */
	private List<PersistentClass> stackOfPersistentClassesBeingProcessed
			= new ArrayList<PersistentClass>();
	private Map<MappedSuperclassTypeImpl mappedSuperClassTypeToPersistentClass
			= new HashMap<MappedSuperclassTypeImpl();

	public MetadataContext(SessionFactoryImplementor sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	/*package*/ SessionFactoryImplementor getSessionFactory() {
		return sessionFactory;
	}

	/**
	 * Retrieves the {@linkplain Class java type} to {@link EntityTypeImpl} map.
	 *
	 * @return The {@linkplain Class java type} to {@link EntityTypeImpl} map.
	 */
	public Map<Class> getEntityTypeMap() {
		return Collections.unmodifiableMap( entityTypes );
	}

	public Map<Class> getEmbeddableTypeMap() {
		return Collections.unmodifiableMap( embeddables );
	}

	/*package*/ void registerEntityType(PersistentClass persistentClass, EntityTypeImpl<?> entityType) {
		entityTypes.put( entityType.getBindableJavaType(), entityType );
		entityTypesByEntityName.put( persistentClass.getEntityName(), entityType );
		entityTypesByPersistentClass.put( persistentClass, entityType );
		orderedMappings.add( persistentClass );
	}

	/*package*/ void registerEmbeddedableType(EmbeddableTypeImpl<?> embeddableType) {
		embeddables.put( embeddableType.getJavaType(), embeddableType );
	}

	/*package*/ void registerMappedSuperclassType(MappedSuperclass mappedSuperclass,
												  MappedSuperclassTypeImpl<?> mappedSuperclassType) {
		mappedSuperclassByMappedSuperclassMapping.put( mappedSuperclass, mappedSuperclassType );
		orderedMappings.add( mappedSuperclass );
		mappedSuperClassTypeToPersistentClass.put( mappedSuperclassType, getEntityWorkedOn() );
	}

	/**
	 * Given a Hibernate {@link PersistentClass}, locate the corresponding JPA {@link org.hibernate.type.EntityType}
	 * implementation.  May retur null if the given {@link PersistentClass} has not yet been processed.
	 *
	 * @param persistentClass The Hibernate (config time) metamodel instance representing an entity.
	 * @return Tne corresponding JPA {@link org.hibernate.type.EntityType}, or null if not yet processed.
	 */
	public EntityTypeImpl<?> locateEntityType(PersistentClass persistentClass) {
		return entityTypesByPersistentClass.get( persistentClass );
	}

	/**
	 * Given a Java {@link Class}, locate the corresponding JPA {@link org.hibernate.type.EntityType}.  May
	 * return null which could means that no such mapping exists at least at this time.
	 *
	 * @param javaType The java class.
	 * @return The corresponding JPA {@link org.hibernate.type.EntityType}, or null.
	 */
	public EntityTypeImpl<?> locateEntityType(Class javaType) {
		return entityTypes.get( javaType );
	}

	/**
	 * Given an entity-name, locate the corresponding JPA {@link org.hibernate.type.EntityType}.  May
	 * return null which could means that no such mapping exists at least at this time.
	 *
	 * @param entityName The entity-name.
	 * @return The corresponding JPA {@link org.hibernate.type.EntityType}, or null.
	 */
	public EntityTypeImpl<?> locateEntityType(String entityName) {
		return entityTypesByEntityName.get( entityName );
	}

	@SuppressWarnings({ "unchecked" })
	public void wrapUp() {
        LOG.trace("Wrapping up metadata context...");
		//we need to process types from superclasses to subclasses
		for (Object mapping : orderedMappings) {
			if ( PersistentClass.class.isAssignableFrom( mapping.getClass() ) ) {
				@SuppressWarnings( "unchecked" )
				final PersistentClass safeMapping = (PersistentClass) mapping;
                LOG.trace("Starting entity [" + safeMapping.getEntityName() + "]");
				try {
					final EntityTypeImpl<?> jpa2Mapping = entityTypesByPersistentClass.get( safeMapping );
					applyIdMetadata( safeMapping, jpa2Mapping );
					applyVersionAttribute( safeMapping, jpa2Mapping );
					Iterator<Property> properties = safeMapping.getDeclaredPropertyIterator();
					while ( properties.hasNext() ) {
						final Property property = properties.next();
						if ( property.getValue() == safeMapping.getIdentifierMapper() ) {
							// property represents special handling for id-class mappings but we have already
							// accounted for the embedded property mappings in #applyIdMetadata &&
							// #buildIdClassAttributes
							continue;
						}
						if ( safeMapping.isVersioned() && property == safeMapping.getVersion() ) {
							// skip the version property, it was already handled previously.
							continue;
						}
						final Attribute attribute = attributeFactory.buildAttribute( jpa2Mapping, property );
						if ( attribute != null ) {
							jpa2Mapping.getBuilder().addAttribute( attribute );
						}
					}
					jpa2Mapping.lock();
					populateStaticMetamodel( jpa2Mapping );
				}
				finally {
                    LOG.trace("Completed entity [" + safeMapping.getEntityName() + "]");
				}
			}
			else if ( MappedSuperclass.class.isAssignableFrom( mapping.getClass() ) ) {
				@SuppressWarnings( "unchecked" )
				final MappedSuperclass safeMapping = (MappedSuperclass) mapping;
                LOG.trace("Starting mapped superclass [" + safeMapping.getMappedClass().getName() + "]");
				try {
					final MappedSuperclassTypeImpl<?> jpa2Mapping = mappedSuperclassByMappedSuperclassMapping.get(
							safeMapping
					);
					applyIdMetadata( safeMapping, jpa2Mapping );
					applyVersionAttribute( safeMapping, jpa2Mapping );
					Iterator<Property> properties = safeMapping.getDeclaredPropertyIterator();
					while ( properties.hasNext() ) {
						final Property property = properties.next();
						if ( safeMapping.isVersioned() && property == safeMapping.getVersion() ) {
							// skip the version property, it was already handled previously.
							continue;
						}
						final Attribute attribute = attributeFactory.buildAttribute( jpa2Mapping, property );
						if ( attribute != null ) {
							jpa2Mapping.getBuilder().addAttribute( attribute );
						}
					}
					jpa2Mapping.lock();
					populateStaticMetamodel( jpa2Mapping );
				}
				finally {
                    LOG.trace("Completed mapped superclass [" + safeMapping.getMappedClass().getName() + "]");
				}
			}
			else {
				throw new AssertionFailure( "Unexpected mapping type: " + mapping.getClass() );
			}
		}

		for ( EmbeddableTypeImpl embeddable : embeddables.values() ) {
			populateStaticMetamodel( embeddable );
		}
	}


	private <X> void applyIdMetadata(PersistentClass persistentClass, EntityTypeImpl jpaEntityType) {
		if ( persistentClass.hasIdentifierProperty() ) {
			final Property declaredIdentifierProperty = persistentClass.getDeclaredIdentifierProperty();
			if (declaredIdentifierProperty != null) {
				jpaEntityType.getBuilder().applyIdAttribute(
						attributeFactory.buildIdAttribute( jpaEntityType, declaredIdentifierProperty )
				);
			}
		}
		else if ( persistentClass.hasIdentifierMapper() ) {
			jpaEntityType.getBuilder().applyIdClassAttributes( buildIdClassAttributes( jpaEntityType, persistentClass ) );
		}
		else {
			final KeyValue value = persistentClass.getIdentifier();
			if (value instanceof Component ) {
				final Component component = ( Component ) value;
				if ( component.getPropertySpan() > 1 ) {
					//FIXME we are an Hibernate embedded id (ie not type)
				}
				else {
					//FIXME take care of declared vs non declared property
					jpaEntityType.getBuilder().applyIdAttribute(
						attributeFactory.buildIdAttribute(
								jpaEntityType,
								(Property) component.getPropertyIterator().next() )
					);
				}
			}
		}
	}

	private <X> void applyIdMetadata(MappedSuperclass mappingType, MappedSuperclassTypeImpl jpaMappingType) {
		if ( mappingType.hasIdentifierProperty() ) {
			final Property declaredIdentifierProperty = mappingType.getDeclaredIdentifierProperty();
			if (declaredIdentifierProperty != null) {
				jpaMappingType.getBuilder().applyIdAttribute(
						attributeFactory.buildIdAttribute( jpaMappingType, declaredIdentifierProperty )
				);
			}
		}
		//an MappedSuperclass can have no identifier if the id is set below in the hierarchy
		else if ( mappingType.getIdentifierMapper() != null ){
			final Set<SingularAttribute attributes = buildIdClassAttributes(
					jpaMappingType, mappingType
			);
			jpaMappingType.getBuilder().applyIdClassAttributes( attributes );
		}
	}

	private <X> void applyVersionAttribute(PersistentClass persistentClass, EntityTypeImpl jpaEntityType) {
		final Property declaredVersion = persistentClass.getDeclaredVersion();
		if (declaredVersion != null) {
			jpaEntityType.getBuilder().applyVersionAttribute(
					attributeFactory.buildVersionAttribute( jpaEntityType, declaredVersion )
			);
		}
	}

	private <X> void applyVersionAttribute(MappedSuperclass mappingType, MappedSuperclassTypeImpl jpaMappingType) {
		final Property declaredVersion = mappingType.getDeclaredVersion();
		if ( declaredVersion != null ) {
			jpaMappingType.getBuilder().applyVersionAttribute(
					attributeFactory.buildVersionAttribute( jpaMappingType, declaredVersion )
			);
		}
	}

	private <X> Set> buildIdClassAttributes(
			EntityTypeImpl<X> jpaEntityType,
			PersistentClass persistentClass) {
		Set<SingularAttribute attributes = new HashSet>();
		@SuppressWarnings( "unchecked")
		Iterator<Property> properties = persistentClass.getIdentifierMapper().getPropertyIterator();
		while ( properties.hasNext() ) {
			attributes.add( attributeFactory.buildIdAttribute( jpaEntityType, properties.next() ) );
		}
		return attributes;
	}

	private <X> Set> buildIdClassAttributes(
			MappedSuperclassTypeImpl<X> jpaMappingType,
			MappedSuperclass mappingType) {
        LOG.trace("Building old-school composite identifier [" + mappingType.getMappedClass().getName() + "]");
		Set<SingularAttribute attributes = new HashSet>();
		@SuppressWarnings( "unchecked" )
		Iterator<Property> properties = mappingType.getIdentifierMapper().getPropertyIterator();
		while ( properties.hasNext() ) {
			attributes.add( attributeFactory.buildIdAttribute( jpaMappingType, properties.next() ) );
		}
		return attributes;
	}

	private <X> void populateStaticMetamodel(AbstractManagedType managedType) {
		final Class<X> managedTypeClass = managedType.getJavaType();
		final String metamodelClassName = managedTypeClass.getName() + "_";
		try {
			final Class metamodelClass = Class.forName( metamodelClassName, true, managedTypeClass.getClassLoader() );
			// we found the class; so populate it...
			registerAttributes( metamodelClass, managedType );
		}
		catch ( ClassNotFoundException ignore ) {
			// nothing to do...
		}

		// todo : this does not account for @MappeSuperclass, mainly because this is not being tracked in our
		// internal metamodel as populated from the annotatios properly
		AbstractManagedType<? super X> superType = managedType.getSupertype();
		if ( superType != null ) {
			populateStaticMetamodel( superType );
		}
	}

	private final Set<Class> processedMetamodelClasses = new HashSet();

	private <X> void registerAttributes(Class metamodelClass, AbstractManagedType managedType) {
		if ( ! processedMetamodelClasses.add( metamodelClass ) ) {
			return;
		}

		// push the attributes on to the metamodel class...
		for ( Attribute<X, ?> attribute : managedType.getDeclaredAttributes() ) {
			registerAttribute( metamodelClass, attribute );
		}

		if ( IdentifiableType.class.isInstance( managedType ) ) {
			final AbstractIdentifiableType<X> entityType = ( AbstractIdentifiableType ) managedType;

			// handle version
			if ( entityType.hasDeclaredVersionAttribute() ) {
				registerAttribute( metamodelClass, entityType.getDeclaredVersion() );
			}

			// handle id-class mappings specially
			if ( ! entityType.hasSingleIdAttribute() ) {
				final Set<SingularAttribute attributes = entityType.getIdClassAttributes();
				if ( attributes != null ) {
					for ( SingularAttribute<? super X, ?> attribute : attributes ) {
						registerAttribute( metamodelClass, attribute );
					}
				}
			}
		}
	}

	private <X> void registerAttribute(Class metamodelClass, Attribute attribute) {
		final String name = attribute.getName();
		try {
			Field field = metamodelClass.getDeclaredField( name );
			try {
				if ( ! field.isAccessible() ) {
					// should be public anyway, but to be sure...
					field.setAccessible( true );
				}
				field.set( null, attribute );
			}
			catch ( IllegalAccessException e ) {
				// todo : exception type?
				throw new AssertionFailure(
						"Unable to inject static metamodel attribute : " + metamodelClass.getName() + '#' + name,
						e
				);
			}
			catch ( IllegalArgumentException e ) {
				// most likely a mismatch in the type we are injecting and the defined field; this represents a
				// mismatch in how the annotation processor interpretted the attribute and how our metamodel
				// and/or annotation binder did.

//              This is particularly the case as arrays are nto handled propery by the StaticMetamodel generator

//				throw new AssertionFailure(
//						"Illegal argument on static metamodel field injection : " + metamodelClass.getName() + '#' + name
//								+ "; expected type :  " + attribute.getClass().getName()
//								+ "; encountered type : " + field.getType().getName()
//				);
                LOG.illegalArgumentOnStaticMetamodelFieldInjection(metamodelClass.getName(),
                                                                   name,
                                                                   attribute.getClass().getName(),
                                                                   field.getType().getName());
			}
		}
		catch ( NoSuchFieldException e ) {
            LOG.unableToLocateStaticMetamodelField(metamodelClass.getName(), name);
//			throw new AssertionFailure(
//					"Unable to locate static metamodel field : " + metamodelClass.getName() + '#' + name
//			);
		}
	}

	public MappedSuperclassTypeImpl<?> locateMappedSuperclassType(MappedSuperclass mappedSuperclass) {
		return mappedSuperclassByMappedSuperclassMapping.get(mappedSuperclass);
	}

	public void pushEntityWorkedOn(PersistentClass persistentClass) {
		stackOfPersistentClassesBeingProcessed.add(persistentClass);
	}

	public void popEntityWorkedOn(PersistentClass persistentClass) {
		final PersistentClass stackTop = stackOfPersistentClassesBeingProcessed.remove(
				stackOfPersistentClassesBeingProcessed.size() - 1
		);
		if (stackTop != persistentClass) {
			throw new AssertionFailure( "Inconsistent popping: "
				+ persistentClass.getEntityName() + " instead of " + stackTop.getEntityName() );
		}
	}

	private PersistentClass getEntityWorkedOn() {
		return stackOfPersistentClassesBeingProcessed.get(
					stackOfPersistentClassesBeingProcessed.size() - 1
			);
	}

	public PersistentClass getPersistentClassHostingProperties(MappedSuperclassTypeImpl<?> mappedSuperclassType) {
		final PersistentClass persistentClass = mappedSuperClassTypeToPersistentClass.get( mappedSuperclassType );
		if (persistentClass == null) {
			throw new AssertionFailure( "Could not find PersistentClass for MappedSuperclassType: "
					+ mappedSuperclassType.getJavaType() );
		}
		return persistentClass;
	}
}

Other Hibernate examples (source code examples)

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