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

org.hibernate.boot.internal.MetadataImpl Maven / Gradle / Ivy

There is a newer version: 7.0.0.Alpha1
Show newest version
/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
 * See the lgpl.txt file in the root directory or .
 */
package org.hibernate.boot.internal;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Pattern;

import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.SessionFactory;
import org.hibernate.boot.SessionFactoryBuilder;
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
import org.hibernate.boot.model.TypeDefinition;
import org.hibernate.boot.model.relational.Database;
import org.hibernate.boot.model.relational.Namespace;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.boot.spi.MetadataBuildingOptions;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.boot.spi.SessionFactoryBuilderFactory;
import org.hibernate.boot.spi.SessionFactoryBuilderImplementor;
import org.hibernate.boot.spi.SessionFactoryBuilderService;
import org.hibernate.cfg.annotations.NamedEntityGraphDefinition;
import org.hibernate.cfg.annotations.NamedProcedureCallDefinition;
import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.engine.ResultSetMappingDefinition;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.engine.spi.NamedQueryDefinition;
import org.hibernate.engine.spi.NamedSQLQueryDefinition;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.event.service.spi.EventListenerGroup;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventType;
import org.hibernate.id.factory.spi.MutableIdentifierGeneratorFactory;
import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.FetchProfile;
import org.hibernate.mapping.MappedSuperclass;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.Table;
import org.hibernate.procedure.ProcedureCallMemento;
import org.hibernate.query.spi.NamedQueryRepository;
import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.type.Type;
import org.hibernate.type.TypeResolver;
import org.hibernate.type.spi.TypeConfiguration;

/**
 * Container for configuration data collected during binding the metamodel.
 *
 * @author Steve Ebersole
 * @author Hardy Ferentschik
 * @author Gail Badner
 */
public class MetadataImpl implements MetadataImplementor, Serializable {
	private static final Pattern LISTENER_SEPARATION_PATTERN = Pattern.compile( " ," );

	private final UUID uuid;
	private final MetadataBuildingOptions metadataBuildingOptions;
	private final BootstrapContext bootstrapContext;

	private final MutableIdentifierGeneratorFactory identifierGeneratorFactory;

	private final Map entityBindingMap;
	private final Map mappedSuperclassMap;
	private final Map collectionBindingMap;
	private final Map typeDefinitionMap;
	private final Map filterDefinitionMap;
	private final Map fetchProfileMap;
	private final Map imports;
	private final Map idGeneratorDefinitionMap;
	private final Map namedQueryMap;
	private final Map namedNativeQueryMap;
	private final Map namedProcedureCallMap;
	private final Map sqlResultSetMappingMap;
	private final Map namedEntityGraphMap;
	private final Map sqlFunctionMap;
	private final Database database;

	public MetadataImpl(
			UUID uuid,
			MetadataBuildingOptions metadataBuildingOptions,
			MutableIdentifierGeneratorFactory identifierGeneratorFactory,
			Map entityBindingMap,
			Map mappedSuperclassMap,
			Map collectionBindingMap,
			Map typeDefinitionMap,
			Map filterDefinitionMap,
			Map fetchProfileMap,
			Map imports,
			Map idGeneratorDefinitionMap,
			Map namedQueryMap,
			Map namedNativeQueryMap,
			Map namedProcedureCallMap,
			Map sqlResultSetMappingMap,
			Map namedEntityGraphMap,
			Map sqlFunctionMap,
			Database database,
			BootstrapContext bootstrapContext) {
		this.uuid = uuid;
		this.metadataBuildingOptions = metadataBuildingOptions;
		this.identifierGeneratorFactory = identifierGeneratorFactory;
		this.entityBindingMap = entityBindingMap;
		this.mappedSuperclassMap = mappedSuperclassMap;
		this.collectionBindingMap = collectionBindingMap;
		this.typeDefinitionMap = typeDefinitionMap;
		this.filterDefinitionMap = filterDefinitionMap;
		this.fetchProfileMap = fetchProfileMap;
		this.imports = imports;
		this.idGeneratorDefinitionMap = idGeneratorDefinitionMap;
		this.namedQueryMap = namedQueryMap;
		this.namedNativeQueryMap = namedNativeQueryMap;
		this.namedProcedureCallMap = namedProcedureCallMap;
		this.sqlResultSetMappingMap = sqlResultSetMappingMap;
		this.namedEntityGraphMap = namedEntityGraphMap;
		this.sqlFunctionMap = sqlFunctionMap;
		this.database = database;
		this.bootstrapContext = bootstrapContext;
	}

	@Override
	public MetadataBuildingOptions getMetadataBuildingOptions() {
		return metadataBuildingOptions;
	}

	@Override
	public TypeConfiguration getTypeConfiguration() {
		return bootstrapContext.getTypeConfiguration();
	}

	/**
	 * Retrieve the {@link Type} resolver associated with this factory.
	 *
	 * @return The type resolver
	 *
	 * @deprecated (since 5.3) No replacement, access to and handling of Types will be much different in 6.0
	 */
	@Deprecated
	public TypeResolver getTypeResolver() {
		return bootstrapContext.getTypeConfiguration().getTypeResolver();
	}

	@Override
	public SessionFactoryBuilder getSessionFactoryBuilder() {
		final SessionFactoryBuilderService factoryBuilderService = metadataBuildingOptions.getServiceRegistry().getService( SessionFactoryBuilderService.class );
		final SessionFactoryBuilderImplementor defaultBuilder = factoryBuilderService.createSessionFactoryBuilder( this, bootstrapContext );

		final ClassLoaderService cls = metadataBuildingOptions.getServiceRegistry().getService( ClassLoaderService.class );
		final java.util.Collection discoveredBuilderFactories = cls.loadJavaServices( SessionFactoryBuilderFactory.class );

		SessionFactoryBuilder builder = null;
		List activeFactoryNames = null;

		for ( SessionFactoryBuilderFactory discoveredBuilderFactory : discoveredBuilderFactories ) {
			final SessionFactoryBuilder returnedBuilder = discoveredBuilderFactory.getSessionFactoryBuilder( this, defaultBuilder );
			if ( returnedBuilder != null ) {
				if ( activeFactoryNames == null ) {
					activeFactoryNames = new ArrayList<>();
				}
				activeFactoryNames.add( discoveredBuilderFactory.getClass().getName() );
				builder = returnedBuilder;
			}
		}

		if ( activeFactoryNames != null && activeFactoryNames.size() > 1 ) {
			throw new HibernateException(
					"Multiple active SessionFactoryBuilderFactory definitions were discovered : " +
							String.join(", ", activeFactoryNames)
			);
		}

		if ( builder != null ) {
			return builder;
		}

		return defaultBuilder;
	}

	@Override
	public SessionFactory buildSessionFactory() {
		return getSessionFactoryBuilder().build();
	}

	@Override
	public UUID getUUID() {
		return uuid;
	}

	@Override
	public Database getDatabase() {
		return database;
	}

	@Override
	public MutableIdentifierGeneratorFactory getIdentifierGeneratorFactory() {
		return identifierGeneratorFactory;
	}

	@Override
	public java.util.Collection getEntityBindings() {
		return entityBindingMap.values();
	}

	@Override
	public PersistentClass getEntityBinding(String entityName) {
		return entityBindingMap.get( entityName );
	}

	@Override
	public java.util.Collection getCollectionBindings() {
		return collectionBindingMap.values();
	}

	@Override
	public Collection getCollectionBinding(String role) {
		return collectionBindingMap.get( role );
	}

	@Override
	public Map getImports() {
		return imports;
	}

	@Override
	public NamedQueryDefinition getNamedQueryDefinition(String name) {
		return namedQueryMap.get( name );
	}

	@Override
	public java.util.Collection getNamedQueryDefinitions() {
		return namedQueryMap.values();
	}

	@Override
	public NamedSQLQueryDefinition getNamedNativeQueryDefinition(String name) {
		return namedNativeQueryMap.get( name );
	}

	@Override
	public java.util.Collection getNamedNativeQueryDefinitions() {
		return namedNativeQueryMap.values();
	}

	@Override
	public java.util.Collection getNamedProcedureCallDefinitions() {
		return namedProcedureCallMap.values();
	}

	@Override
	public ResultSetMappingDefinition getResultSetMapping(String name) {
		return sqlResultSetMappingMap.get( name );
	}

	@Override
	public Map getResultSetMappingDefinitions() {
		return sqlResultSetMappingMap;
	}

	@Override
	public TypeDefinition getTypeDefinition(String typeName) {
		return typeDefinitionMap.get( typeName );
	}

	@Override
	public Map getFilterDefinitions() {
		return filterDefinitionMap;
	}

	@Override
	public FilterDefinition getFilterDefinition(String name) {
		return filterDefinitionMap.get( name );
	}

	@Override
	public FetchProfile getFetchProfile(String name) {
		return fetchProfileMap.get( name );
	}

	@Override
	public java.util.Collection getFetchProfiles() {
		return fetchProfileMap.values();
	}

	@Override
	public NamedEntityGraphDefinition getNamedEntityGraph(String name) {
		return namedEntityGraphMap.get( name );
	}

	@Override
	public Map getNamedEntityGraphs() {
		return namedEntityGraphMap;
	}

	@Override
	public IdentifierGeneratorDefinition getIdentifierGenerator(String name) {
		return idGeneratorDefinitionMap.get( name );
	}

	@Override
	public Map getSqlFunctionMap() {
		return sqlFunctionMap;
	}

	@Override
	public java.util.Collection collectTableMappings() {
		ArrayList
tables = new ArrayList<>(); for ( Namespace namespace : database.getNamespaces() ) { tables.addAll( namespace.getTables() ); } return tables; } @Override public NamedQueryRepository buildNamedQueryRepository(SessionFactoryImpl sessionFactory) { return new NamedQueryRepository( namedQueryMap, namedNativeQueryMap, sqlResultSetMappingMap, buildProcedureCallMementos( sessionFactory ) ); } private Map buildProcedureCallMementos(SessionFactoryImpl sessionFactory) { final Map rtn = new HashMap<>(); if ( namedProcedureCallMap != null ) { for ( NamedProcedureCallDefinition procedureCallDefinition : namedProcedureCallMap.values() ) { rtn.put( procedureCallDefinition.getRegisteredName(), procedureCallDefinition.toMemento( sessionFactory,sqlResultSetMappingMap ) ); } } return rtn; } @Override public void validate() throws MappingException { for ( PersistentClass entityBinding : this.getEntityBindings() ) { entityBinding.validate( this ); } for ( Collection collectionBinding : this.getCollectionBindings() ) { collectionBinding.validate( this ); } } @Override public Set getMappedSuperclassMappingsCopy() { return mappedSuperclassMap == null ? Collections.emptySet() : new HashSet<>( mappedSuperclassMap.values() ); } @Override public void initSessionFactory(SessionFactoryImplementor sessionFactory) { final ServiceRegistryImplementor sessionFactoryServiceRegistry = sessionFactory.getServiceRegistry(); assert sessionFactoryServiceRegistry != null; final EventListenerRegistry eventListenerRegistry = sessionFactoryServiceRegistry.getService( EventListenerRegistry.class ); final ConfigurationService cfgService = sessionFactoryServiceRegistry.getService( ConfigurationService.class ); final ClassLoaderService classLoaderService = sessionFactoryServiceRegistry.getService( ClassLoaderService.class ); for ( Map.Entry entry : ( (Map) cfgService.getSettings() ).entrySet() ) { if ( !String.class.isInstance( entry.getKey() ) ) { continue; } final String propertyName = (String) entry.getKey(); if ( !propertyName.startsWith( org.hibernate.jpa.AvailableSettings.EVENT_LISTENER_PREFIX ) ) { continue; } final String eventTypeName = propertyName.substring( org.hibernate.jpa.AvailableSettings.EVENT_LISTENER_PREFIX.length() + 1 ); final EventType eventType = EventType.resolveEventTypeByName( eventTypeName ); final EventListenerGroup eventListenerGroup = eventListenerRegistry.getEventListenerGroup( eventType ); for ( String listenerImpl : LISTENER_SEPARATION_PATTERN.split( ( (String) entry.getValue() ) ) ) { eventListenerGroup.appendListener( instantiate( listenerImpl, classLoaderService ) ); } } } private Object instantiate(String listenerImpl, ClassLoaderService classLoaderService) { try { return classLoaderService.classForName( listenerImpl ).newInstance(); } catch (Exception e) { throw new HibernateException( "Could not instantiate requested listener [" + listenerImpl + "]", e ); } } @Override public org.hibernate.type.Type getIdentifierType(String entityName) throws MappingException { final PersistentClass pc = entityBindingMap.get( entityName ); if ( pc == null ) { throw new MappingException( "persistent class not known: " + entityName ); } return pc.getIdentifier().getType(); } @Override public String getIdentifierPropertyName(String entityName) throws MappingException { final PersistentClass pc = entityBindingMap.get( entityName ); if ( pc == null ) { throw new MappingException( "persistent class not known: " + entityName ); } if ( !pc.hasIdentifierProperty() ) { return null; } return pc.getIdentifierProperty().getName(); } @Override public org.hibernate.type.Type getReferencedPropertyType(String entityName, String propertyName) throws MappingException { final PersistentClass pc = entityBindingMap.get( entityName ); if ( pc == null ) { throw new MappingException( "persistent class not known: " + entityName ); } Property prop = pc.getReferencedProperty( propertyName ); if ( prop == null ) { throw new MappingException( "property not known: " + entityName + '.' + propertyName ); } return prop.getType(); } //Specific for copies only: public Map getEntityBindingMap() { return entityBindingMap; } public Map getCollectionBindingMap() { return collectionBindingMap; } public Map getTypeDefinitionMap() { return typeDefinitionMap; } public Map getFetchProfileMap() { return fetchProfileMap; } public Map getMappedSuperclassMap() { return mappedSuperclassMap; } public Map getIdGeneratorDefinitionMap() { return idGeneratorDefinitionMap; } public Map getNamedQueryMap() { return namedQueryMap; } public Map getNamedNativeQueryMap() { return namedNativeQueryMap; } public Map getNamedProcedureCallMap() { return namedProcedureCallMap; } public Map getSqlResultSetMappingMap() { return sqlResultSetMappingMap; } public Map getNamedEntityGraphMap() { return namedEntityGraphMap; } public BootstrapContext getBootstrapContext() { return bootstrapContext; } }