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

org.hibernate.query.sqm.tree.domain.SqmPolymorphicRootDescriptor Maven / Gradle / Ivy

There is a newer version: 7.0.0.Alpha3
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 http://www.gnu.org/licenses/lgpl-2.1.html
 */
package org.hibernate.query.sqm.tree.domain;

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.function.Consumer;
import java.util.stream.Collectors;
import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.CollectionAttribute;
import javax.persistence.metamodel.ListAttribute;
import javax.persistence.metamodel.MapAttribute;
import javax.persistence.metamodel.PluralAttribute;
import javax.persistence.metamodel.SetAttribute;
import javax.persistence.metamodel.SingularAttribute;

import org.hibernate.graph.spi.SubGraphImplementor;
import org.hibernate.metamodel.RepresentationMode;
import org.hibernate.metamodel.model.domain.DomainType;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.metamodel.model.domain.IdentifiableDomainType;
import org.hibernate.metamodel.model.domain.ManagedDomainType;
import org.hibernate.metamodel.model.domain.PersistentAttribute;
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
import org.hibernate.metamodel.model.domain.SimpleDomainType;
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;

/**
 * Acts as the EntityValuedNavigable for a "polymorphic query" grouping
 *
 * @author Steve Ebersole
 */
public class SqmPolymorphicRootDescriptor implements EntityDomainType {
	private final Set> implementors;
	private final Map commonAttributes;

	private final JavaTypeDescriptor polymorphicJavaDescriptor;

	public SqmPolymorphicRootDescriptor(
			JavaTypeDescriptor polymorphicJavaDescriptor,
			Set> implementors) {
		this.polymorphicJavaDescriptor = polymorphicJavaDescriptor;

		this.implementors = implementors;

		final Map workMap = new HashMap<>();

		final ArrayList> implementorsList = new ArrayList<>( implementors );

		final EntityDomainType firstImplementor = implementorsList.get( 0 );

		// basically we want to "expose" only the attributes that all the implementors expose...
		// 		- visit all of the attributes defined on the first implementor and check it against
		// 		all of the others
		final List> subList = implementorsList.subList( 1, implementors.size() - 1 );
		firstImplementor.visitAttributes(
				attribute -> {
					// for each of its attributes, check whether the other implementors also expose it
					for ( EntityDomainType navigable : subList ) {
						if ( navigable.findAttribute( attribute.getName() ) == null ) {
							// we found an implementor that does not expose that attribute,
							// so break-out to the next attribute
							break;
						}

						// if we get here - they all had it.  so put it in the workMap
						//
						// todo (6.0) : Atm We use the attribute from the first implementor directly for each implementor
						//		need to handle this in QuerySplitter somehow
						workMap.put( attribute.getName(), attribute );
					}

				}
		);
		this.commonAttributes = Collections.unmodifiableMap( workMap );
	}

	public Set> getImplementors() {
		return new HashSet<>( implementors );
	}

	@Override
	public String getName() {
		return polymorphicJavaDescriptor.getJavaType().getName();
	}

	@Override
	public String getHibernateEntityName() {
		return getName();
	}

	@Override
	public String getTypeName() {
		return getName();
	}

	@Override
	public String getPathName() {
		return getName();
	}

	@Override
	public DomainType getSqmPathType() {
		return this;
	}

	@Override
	public BindableType getBindableType() {
		return BindableType.ENTITY_TYPE;
	}

	@Override
	public Class getBindableJavaType() {
		return polymorphicJavaDescriptor.getJavaType();
	}

	@Override
	public PersistenceType getPersistenceType() {
		return PersistenceType.ENTITY;
	}

	@Override
	public Class getJavaType() {
		return getBindableJavaType();
	}

	@Override
	public JavaTypeDescriptor getExpressableJavaTypeDescriptor() {
		return polymorphicJavaDescriptor;
	}

	// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Attribute handling

	@Override
	@SuppressWarnings("unchecked")
	public PersistentAttribute findAttribute(String name) {
		return commonAttributes.get( name );
	}

	@Override
	public void visitAttributes(Consumer> action) {
		commonAttributes.values().forEach( (Consumer) action );
	}

	@Override
	public void visitDeclaredAttributes(Consumer> action) {
	}

	@Override
	public PersistentAttribute getAttribute(String name) {
		final PersistentAttribute attribute = findAttribute( name );
		if ( attribute == null ) {
			// per-JPA
			throw new IllegalArgumentException();
		}
		return attribute;
	}

	@Override
	public PersistentAttribute getDeclaredAttribute(String name) {
		throw new IllegalArgumentException();
	}

	@Override
	public SingularPersistentAttribute findSingularAttribute(String name) {
		//noinspection unchecked
		return (SingularPersistentAttribute) findAttribute( name );
	}

	@Override
	public PluralPersistentAttribute findPluralAttribute(String name) {
		//noinspection unchecked
		return (PluralPersistentAttribute) findAttribute( name );
	}

	@Override
	public PersistentAttribute findDeclaredAttribute(String name) {
		return null;
	}

	@Override
	public SingularPersistentAttribute findDeclaredSingularAttribute(String name) {
		return null;
	}

	@Override
	public PluralPersistentAttribute findDeclaredPluralAttribute(String name) {
		return null;
	}

	@Override
	public Set> getAttributes() {
		//noinspection unchecked
		return (Set>) commonAttributes;
	}

	@Override
	public Set> getDeclaredAttributes() {
		return Collections.emptySet();
	}

	@Override
	public  SingularAttribute getSingularAttribute(String name, Class type) {
		//noinspection unchecked
		return (SingularAttribute) getAttribute( name );
	}

	@Override
	public  SingularAttribute getDeclaredSingularAttribute(String name, Class type) {
		//noinspection unchecked
		return (SingularAttribute) getDeclaredAttribute( name );
	}

	@Override
	public Set> getSingularAttributes() {
		//noinspection unchecked
		return (Set) commonAttributes.values().stream()
				.filter( attribute -> attribute instanceof SingularAttribute )
				.collect( Collectors.toSet() );
	}

	@Override
	public Set> getDeclaredSingularAttributes() {
		return Collections.emptySet();
	}

	@Override
	public  CollectionAttribute getCollection(String name, Class elementType) {
		//noinspection unchecked
		return (CollectionAttribute) getAttribute( name );
	}

	@Override
	public  CollectionAttribute getDeclaredCollection(String name, Class elementType) {
		throw new IllegalArgumentException();
	}

	@Override
	public  SetAttribute getSet(String name, Class elementType) {
		//noinspection unchecked
		return (SetAttribute) getAttribute( name );
	}

	@Override
	public  SetAttribute getDeclaredSet(String name, Class elementType) {
		throw new IllegalArgumentException(  );
	}

	@Override
	public  ListAttribute getList(String name, Class elementType) {
		//noinspection unchecked
		return (ListAttribute) getAttribute( name );
	}

	@Override
	public  ListAttribute getDeclaredList(String name, Class elementType) {
		throw new IllegalArgumentException();
	}

	@Override
	public  MapAttribute getMap(String name, Class keyType, Class valueType) {
		//noinspection unchecked
		return (MapAttribute) getAttribute( name );
	}

	@Override
	public  MapAttribute getDeclaredMap(String name, Class keyType, Class valueType) {
		throw new IllegalArgumentException();
	}

	@Override
	public Set> getPluralAttributes() {
		//noinspection unchecked
		return (Set) commonAttributes.values().stream()
				.filter( attribute -> attribute instanceof PluralAttribute )
				.collect( Collectors.toSet() );
	}

	@Override
	public Set> getDeclaredPluralAttributes() {
		return Collections.emptySet();
	}

	@Override
	public SingularAttribute getSingularAttribute(String name) {
		//noinspection unchecked
		return (SingularAttribute) getAttribute( name );
	}

	@Override
	public SingularAttribute getDeclaredSingularAttribute(String name) {
		throw new IllegalArgumentException();
	}

	@Override
	public CollectionAttribute getCollection(String name) {
		//noinspection unchecked
		return (CollectionAttribute) getAttribute( name );
	}

	@Override
	public CollectionAttribute getDeclaredCollection(String name) {
		throw new IllegalArgumentException();
	}

	@Override
	public SetAttribute getSet(String name) {
		//noinspection unchecked
		return (SetAttribute) getAttribute( name );
	}

	@Override
	public SetAttribute getDeclaredSet(String name) {
		throw new IllegalArgumentException();
	}

	@Override
	public ListAttribute getList(String name) {
		//noinspection unchecked
		return (ListAttribute) getAttribute( name );
	}

	@Override
	public ListAttribute getDeclaredList(String name) {
		throw new IllegalArgumentException();
	}

	@Override
	public MapAttribute getMap(String name) {
		//noinspection unchecked
		return (MapAttribute) getAttribute( name );
	}

	@Override
	public MapAttribute getDeclaredMap(String name) {
		throw new IllegalArgumentException();
	}

	@Override
	public SqmPathSource findSubPathSource(String name) {
		return (SqmPathSource) findAttribute( name );
	}

	@Override
	public SqmPath createSqmPath(SqmPath lhs, SqmCreationState creationState) {
		throw new UnsupportedOperationException();
	}


	// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Unsupported operations

	@Override
	public RepresentationMode getRepresentationMode() {
		return RepresentationMode.POJO;
	}

	@Override
	public SubGraphImplementor makeSubGraph() {
		throw new UnsupportedOperationException(  );
	}

	@Override
	public  SubGraphImplementor makeSubGraph(Class subType) {
		throw new UnsupportedOperationException(  );
	}

	@Override
	public  ManagedDomainType findSubType(String subTypeName) {
		// technically we could support this
		throw new UnsupportedOperationException(  );
	}

	@Override
	public  ManagedDomainType findSubType(Class type) {
		// technically we could support this
		throw new UnsupportedOperationException(  );
	}

	@Override
	public SqmPathSource getIdentifierDescriptor() {
		return null;
	}

	@Override
	public  SingularPersistentAttribute getId(Class type) {
		throw new UnsupportedOperationException(  );
	}

	@Override
	public  SingularPersistentAttribute getDeclaredId(Class type) {
		throw new UnsupportedOperationException(  );
	}

	@Override
	public  SingularPersistentAttribute getVersion(Class type) {
		throw new UnsupportedOperationException(  );
	}

	@Override
	public  SingularPersistentAttribute getDeclaredVersion(Class type) {
		throw new UnsupportedOperationException(  );
	}

	@Override
	public Set> getIdClassAttributes() {
		throw new UnsupportedOperationException(  );
	}

	@Override
	public SimpleDomainType getIdType() {
		throw new UnsupportedOperationException(  );
	}

	@Override
	public IdentifiableDomainType getSupertype() {
		throw new UnsupportedOperationException(  );
	}

	@Override
	public boolean hasIdClass() {
		throw new UnsupportedOperationException(  );
	}

	@Override
	public SingularPersistentAttribute findIdAttribute() {
		throw new UnsupportedOperationException(  );
	}

	@Override
	public void visitIdClassAttributes(Consumer> action) {
	}

	@Override
	public SingularPersistentAttribute findVersionAttribute() {
		throw new UnsupportedOperationException(  );
	}

	@Override
	public boolean hasSingleIdAttribute() {
		throw new UnsupportedOperationException(  );
	}

	@Override
	public boolean hasVersionAttribute() {
		throw new UnsupportedOperationException(  );
	}

	@Override
	public ManagedDomainType getSuperType() {
		throw new UnsupportedOperationException(  );
	}
}