/* * 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.produce.internal.hql.navigable; import org.hibernate.query.sqm.domain.SqmExpressableTypeEntity; import org.hibernate.query.sqm.domain.SqmNavigable; import org.hibernate.query.sqm.SemanticException; import org.hibernate.query.sqm.produce.spi.ResolutionContext; import org.hibernate.query.sqm.tree.SqmJoinType; import org.hibernate.query.sqm.tree.expression.domain.SqmAttributeReference; import org.hibernate.query.sqm.tree.expression.domain.SqmNavigableReference; import org.hibernate.query.sqm.tree.expression.domain.SqmNavigableSourceReference; import org.hibernate.query.sqm.tree.from.SqmFromElementSpace; import org.hibernate.query.sqm.tree.from.SqmFromExporter; /** * PathResolver implementation for resolving path references as part of a * SqmFromClause (join paths mainly). * * @author Steve Ebersole */ public class PathResolverJoinAttributeImpl extends PathResolverBasicImpl { private final SqmFromElementSpace fromElementSpace; private final SqmJoinType joinType; private final String alias; private final boolean fetched; public PathResolverJoinAttributeImpl( ResolutionContext resolutionContext, SqmFromElementSpace fromElementSpace, SqmJoinType joinType, String alias, boolean fetched) { super( resolutionContext ); this.fromElementSpace = fromElementSpace; this.joinType = joinType; this.alias = alias; this.fetched = fetched; } @Override public boolean canReuseImplicitJoins() { return false; } @Override protected SqmJoinType getIntermediateJoinType() { return joinType; } protected boolean areIntermediateJoinsFetched() { return fetched; } @Override protected SqmNavigableReference resolveTerminalAttributeBinding( SqmNavigableSourceReference sourceBinding, String terminalName) { final SqmNavigable attribute = resolveNavigable( sourceBinding, terminalName ); return resolveTerminal( sourceBinding, attribute, null ); } private SqmAttributeReference resolveTerminal( SqmNavigableSourceReference sourceBinding, SqmNavigable navigable, SqmExpressableTypeEntity subclassIndicator) { final SqmAttributeReference attributeBinding = (SqmAttributeReference) context().getParsingContext() .findOrCreateNavigableBinding( sourceBinding, navigable ); if ( attributeBinding.getExportedFromElement() == null ) { // create the join and inject it into the binding attributeBinding.injectExportedFromElement( context().getFromElementBuilder().buildAttributeJoin( attributeBinding, alias, subclassIndicator, getIntermediateJoinType(), areIntermediateJoinsFetched(), canReuseImplicitJoins() ) ); } return attributeBinding; } @Override protected SqmNavigableReference resolveTreatedTerminal( ResolutionContext context, SqmNavigableSourceReference sourceBinding, String terminalName, SqmExpressableTypeEntity subclassIndicator) { final SqmNavigable attribute = resolveNavigable( sourceBinding, terminalName ); return resolveTerminal( sourceBinding, attribute, subclassIndicator ); } @Override protected SqmNavigableReference resolveFromElementAliasAsTerminal(SqmFromExporter exporter) { // this can never be valid... throw new SemanticException( "Cannot join to aliased FromElement [" + exporter.getExportedFromElement().getIdentificationVariable() + "]" ); } }