All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hibernate.metamodel.source.hbm.HierarchyBuilder Maven / Gradle / Ivy

There is a newer version: 7.0.0.Alpha1
Show newest version
/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * Copyright (c) 2011, 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.metamodel.source.hbm;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.hibernate.MappingException;
import org.hibernate.internal.jaxb.mapping.hbm.EntityElement;
import org.hibernate.internal.jaxb.mapping.hbm.JaxbHibernateMapping;
import org.hibernate.internal.jaxb.mapping.hbm.JaxbJoinedSubclassElement;
import org.hibernate.internal.jaxb.mapping.hbm.JaxbSubclassElement;
import org.hibernate.internal.jaxb.mapping.hbm.JaxbUnionSubclassElement;
import org.hibernate.internal.jaxb.mapping.hbm.SubEntityElement;
import org.hibernate.metamodel.source.binder.SubclassEntityContainer;
import org.hibernate.metamodel.source.binder.SubclassEntitySource;

/**
 * @author Steve Ebersole
 */
public class HierarchyBuilder {
	private final List entityHierarchies = new ArrayList();

	// process state
	private final Map subEntityContainerMap = new HashMap();
	private final List extendsQueue = new ArrayList();

	// mapping file specific state
	private MappingDocument currentMappingDocument;

	public void processMappingDocument(MappingDocument mappingDocument) {
		this.currentMappingDocument = mappingDocument;
		try {
			processCurrentMappingDocument();
		}
		finally {
			this.currentMappingDocument = null;
		}
	}

	private void processCurrentMappingDocument() {
		for ( Object entityElementO : currentMappingDocument.getMappingRoot().getClazzOrSubclassOrJoinedSubclass() ) {
			final EntityElement entityElement = (EntityElement) entityElementO;
			if ( JaxbHibernateMapping.JaxbClass.class.isInstance( entityElement ) ) {
				// we can immediately handle  elements in terms of creating the hierarchy entry
				final JaxbHibernateMapping.JaxbClass jaxbClass = (JaxbHibernateMapping.JaxbClass) entityElement;
				final RootEntitySourceImpl rootEntitySource = new RootEntitySourceImpl( currentMappingDocument,
																						jaxbClass
				);
				final EntityHierarchyImpl hierarchy = new EntityHierarchyImpl( rootEntitySource );

				entityHierarchies.add( hierarchy );
				subEntityContainerMap.put( rootEntitySource.getEntityName(), rootEntitySource );

				processSubElements( entityElement, rootEntitySource );
			}
			else {
				// we have to see if this things super-type has been found yet, and if not add it to the
				// extends queue
				final SubclassEntitySourceImpl subClassEntitySource = new SubclassEntitySourceImpl( currentMappingDocument, entityElement );
				final String entityName = subClassEntitySource.getEntityName();
				subEntityContainerMap.put( entityName, subClassEntitySource );
				final String entityItExtends = currentMappingDocument.getMappingLocalBindingContext().qualifyClassName(
						((SubEntityElement) entityElement).getExtends()
				);
				processSubElements( entityElement, subClassEntitySource );
				final SubclassEntityContainer container = subEntityContainerMap.get( entityItExtends );
				if ( container != null ) {
					// we already have this entity's super, attach it and continue
					container.add( subClassEntitySource );
				}
				else {
					// we do not yet have the super and have to wait, so add it fto the extends queue
					extendsQueue.add( new ExtendsQueueEntry( subClassEntitySource, entityItExtends ) );
				}
			}
		}
	}

	public List groupEntityHierarchies() {
		while ( ! extendsQueue.isEmpty() ) {
			// set up a pass over the queue
			int numberOfMappingsProcessed = 0;
			Iterator iterator = extendsQueue.iterator();
			while ( iterator.hasNext() ) {
				final ExtendsQueueEntry entry = iterator.next();
				final SubclassEntityContainer container = subEntityContainerMap.get( entry.entityItExtends );
				if ( container != null ) {
					// we now have this entity's super, attach it and remove entry from extends queue
					container.add( entry.subClassEntitySource );
					iterator.remove();
					numberOfMappingsProcessed++;
				}
			}

			if ( numberOfMappingsProcessed == 0 ) {
				// todo : we could log the waiting dependencies...
				throw new MappingException( "Unable to process extends dependencies in hbm files" );
			}
		}

		return entityHierarchies;
	}

	private void processSubElements(EntityElement entityElement, SubclassEntityContainer container) {
		if ( JaxbHibernateMapping.JaxbClass.class.isInstance( entityElement ) ) {
			final JaxbHibernateMapping.JaxbClass jaxbClass = (JaxbHibernateMapping.JaxbClass) entityElement;
			processElements( jaxbClass.getJoinedSubclass(), container );
			processElements( jaxbClass.getSubclass(), container );
			processElements( jaxbClass.getUnionSubclass(), container );
		}
		else if ( JaxbSubclassElement.class.isInstance( entityElement ) ) {
			final JaxbSubclassElement jaxbSubclass = (JaxbSubclassElement) entityElement;
			processElements( jaxbSubclass.getSubclass(), container );
		}
		else if ( JaxbJoinedSubclassElement.class.isInstance( entityElement ) ) {
			final JaxbJoinedSubclassElement jaxbJoinedSubclass = (JaxbJoinedSubclassElement) entityElement;
			processElements( jaxbJoinedSubclass.getJoinedSubclass(), container );
		}
		else if ( JaxbUnionSubclassElement.class.isInstance( entityElement ) ) {
			final JaxbUnionSubclassElement jaxbUnionSubclass = (JaxbUnionSubclassElement) entityElement;
			processElements( jaxbUnionSubclass.getUnionSubclass(), container );
		}
	}

	private void processElements(List subElements, SubclassEntityContainer container) {
		for ( Object subElementO : subElements ) {
			final SubEntityElement subElement = (SubEntityElement) subElementO;
			final SubclassEntitySourceImpl subclassEntitySource = new SubclassEntitySourceImpl( currentMappingDocument, subElement );
			container.add( subclassEntitySource );
			final String subEntityName = subclassEntitySource.getEntityName();
			subEntityContainerMap.put( subEntityName, subclassEntitySource );
		}
	}

	private static class ExtendsQueueEntry {
		private final SubclassEntitySource subClassEntitySource;
		private final String entityItExtends;

		private ExtendsQueueEntry(SubclassEntitySource subClassEntitySource, String entityItExtends) {
			this.subClassEntitySource = subClassEntitySource;
			this.entityItExtends = entityItExtends;
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy