/*
* 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 java.util.Collections;
import java.util.List;
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.SqmExpressableTypeEmbedded;
import org.hibernate.query.sqm.domain.SqmExpressableTypeEntity;
import org.hibernate.query.sqm.ParsingException;
import org.hibernate.query.sqm.produce.spi.AbstractQuerySpecProcessingState;
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.from.SqmFromElementSpace;
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
import org.hibernate.query.sqm.tree.from.SqmCrossJoin;
import org.hibernate.query.sqm.tree.from.SqmEntityJoin;
import org.hibernate.query.sqm.tree.from.SqmFromClause;
import org.hibernate.query.sqm.tree.from.SqmJoin;
import org.hibernate.query.sqm.tree.from.SqmRoot;
/**
* QuerySpecProcessingState implementation for DML statements
*
* @author Steve Ebersole
*/
public class QuerySpecProcessingStateDmlImpl extends AbstractQuerySpecProcessingState {
private final DmlFromClause fromClause;
private final FromElementBuilder fromElementBuilder;
public QuerySpecProcessingStateDmlImpl(ParsingContext parsingContext) {
// implicitly no outer query, so pass null
super( parsingContext, null );
this.fromClause = new DmlFromClause();
this.fromElementBuilder = new DmlFromElementBuilder( parsingContext, new AliasRegistry() );
}
@Override
public DmlFromClause getFromClause() {
return fromClause;
}
@Override
public SqmNavigableReference findNavigableBindingByIdentificationVariable(String identificationVariable) {
return fromClause.fromElementSpace.getRoot().getIdentificationVariable().equals( identificationVariable )
? fromClause.fromElementSpace.getRoot().getBinding()
: null;
}
@Override
public SqmNavigableReference findNavigableBindingExposingAttribute(String attributeName) {
if ( rootExposesAttribute( attributeName ) ) {
return fromClause.fromElementSpace.getRoot().getBinding();
}
else {
return null;
}
}
private boolean rootExposesAttribute(String attributeName) {
return null != fromClause.fromElementSpace.getRoot().getBinding().getReferencedNavigable().findNavigable( attributeName );
}
@Override
public FromElementLocator getFromElementLocator() {
return this;
}
@Override
public FromElementBuilder getFromElementBuilder() {
return fromElementBuilder;
}
public DmlSqmFromElementSpace getDmlFromElementSpace() {
return fromClause.fromElementSpace;
}
public static class DmlFromClause extends SqmFromClause {
private final DmlSqmFromElementSpace fromElementSpace = new DmlSqmFromElementSpace( this );
@Override
public List<SqmFromElementSpace> getFromElementSpaces() {
return Collections.singletonList( fromElementSpace );
}
@Override
public void addFromElementSpace(SqmFromElementSpace space) {
throw new ParsingException( "DML from-clause cannot have additional FromElementSpaces" );
}
@Override
public SqmFromElementSpace makeFromElementSpace() {
throw new ParsingException( "DML from-clause cannot have additional FromElementSpaces" );
}
}
public static class DmlSqmFromElementSpace extends SqmFromElementSpace {
private DmlSqmFromElementSpace(DmlFromClause fromClause) {
super( fromClause );
}
@Override
public void setRoot(SqmRoot root) {
super.setRoot( root );
}
@Override
public List<SqmJoin> getJoins() {
return Collections.emptyList();
}
@Override
public void addJoin(SqmJoin join) {
throw new ParsingException( "DML from-clause cannot define joins" );
}
}
public static class DmlFromElementBuilder extends FromElementBuilder {
public DmlFromElementBuilder(ParsingContext parsingContext, AliasRegistry aliasRegistry) {
super( parsingContext, aliasRegistry );
}
@Override
public SqmCrossJoin makeCrossJoinedFromElement(
SqmFromElementSpace fromElementSpace, String uid, SqmExpressableTypeEntity entityType, String alias) {
throw new ParsingException( "DML from-clause cannot define joins" );
}
@Override
public SqmEntityJoin buildEntityJoin(
SqmFromElementSpace fromElementSpace,
String alias,
SqmExpressableTypeEntity entityType,
SqmJoinType joinType) {
throw new ParsingException( "DML from-clause cannot define joins" );
}
@Override
public SqmAttributeJoin buildAttributeJoin(
SqmAttributeReference attributeBinding,
String alias,
SqmExpressableTypeEntity subclassIndicator,
SqmJoinType joinType,
boolean fetched,
boolean canReuseImplicitJoins) {
if ( SqmExpressableTypeEmbedded.class.isInstance( attributeBinding.getReferencedNavigable() ) ) {
return super.buildAttributeJoin(
attributeBinding,
alias,
subclassIndicator,
joinType,
fetched,
canReuseImplicitJoins
);
}
throw new ParsingException( "DML from-clause cannot define joins" );
}
}
}