/* * 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; import org.hibernate.query.sqm.produce.spi.AliasRegistry; import org.hibernate.query.sqm.produce.spi.FromElementLocator; import org.hibernate.query.sqm.produce.spi.ParsingContext; import org.hibernate.query.sqm.domain.SqmNavigable; import org.hibernate.query.sqm.produce.spi.AbstractQuerySpecProcessingState; import org.hibernate.query.sqm.produce.spi.QuerySpecProcessingState; 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.SqmFromClause; import org.hibernate.query.sqm.tree.from.SqmJoin; import org.jboss.logging.Logger; /** * Models the state related to parsing a sqm spec. As a "linked list" to account for * subqueries * * @author Steve Ebersole * @author Andrea Boriero */ public class QuerySpecProcessingStateStandardImpl extends AbstractQuerySpecProcessingState { private static final Logger log = Logger.getLogger( QuerySpecProcessingStateStandardImpl.class ); private final SqmFromClause fromClause; private final FromElementBuilder fromElementBuilder; public QuerySpecProcessingStateStandardImpl(ParsingContext parsingContext, QuerySpecProcessingState containingQueryState) { super( parsingContext, containingQueryState ); this.fromClause = new SqmFromClause(); if ( containingQueryState == null ) { this.fromElementBuilder = new FromElementBuilder( parsingContext, new AliasRegistry() ); } else { this.fromElementBuilder = new FromElementBuilder( parsingContext, new AliasRegistry( containingQueryState.getFromElementBuilder().getAliasRegistry() ) ); } } public SqmFromClause getFromClause() { return fromClause; } @Override public FromElementBuilder getFromElementBuilder() { return fromElementBuilder; } @Override public SqmNavigableReference findNavigableBindingByIdentificationVariable(String identificationVariable) { return fromElementBuilder.getAliasRegistry().findFromElementByAlias( identificationVariable ); } @Override public SqmNavigableReference findNavigableBindingExposingAttribute(String name) { SqmNavigableReference found = null; for ( SqmFromElementSpace space : fromClause.getFromElementSpaces() ) { if ( definesAttribute( space.getRoot().getBinding(), name ) ) { if ( found != null ) { throw new IllegalStateException( "Multiple from-elements expose unqualified attribute : " + name ); } found = space.getRoot().getBinding(); } for ( SqmJoin join : space.getJoins() ) { if ( definesAttribute( join.getBinding(), name ) ) { if ( found != null ) { throw new IllegalStateException( "Multiple from-elements expose unqualified attribute : " + name ); } found = join.getBinding(); } } } if ( found == null ) { if ( getContainingQueryState() != null ) { log.debugf( "Unable to resolve unqualified attribute [%s] in local SqmFromClause; checking containingQueryState" ); found = getContainingQueryState().findNavigableBindingExposingAttribute( name ); } } return found; } private boolean definesAttribute(SqmNavigableReference sourceBinding, String name) { if ( !SqmNavigableSourceReference.class.isInstance( sourceBinding ) ) { return false; } final SqmNavigable navigable = ( (SqmNavigableSourceReference) sourceBinding ).getReferencedNavigable().findNavigable( name ); return navigable != null; } private boolean definesAttribute(SqmNavigableSourceReference sourceBinding, String name) { final SqmNavigable navigable = sourceBinding.getReferencedNavigable().findNavigable( name ); return navigable != null; } @Override public FromElementLocator getFromElementLocator() { return this; } }