/*
* 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.persister.queryable.spi.ExpressableType;
import org.hibernate.persister.common.spi.Navigable;
import org.hibernate.persister.queryable.spi.EntityValuedExpressableType;
import org.hibernate.query.spi.NavigablePath;
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
import org.hibernate.query.sqm.tree.expression.domain.AbstractSqmNavigableReference;
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.SqmDowncast;
import org.hibernate.query.sqm.tree.from.SqmFrom;
import org.hibernate.query.sqm.tree.from.SqmFromExporter;
/**
* Models an "incidental downcast", as opposed to an intrinsic downcast. An
* intrinsic downcast occurs in the from-clause - the downcast target becomes
* an intrinsic part of the FromElement (see {@link SqmFrom#getIntrinsicSubclassIndicator()}.
* An incidental downcast, on the other hand, occurs outside the from-clause.
* <p/>
* For example,
* {@code .. from Person p where treat(p.address as USAddress).zip=? ...} represents
* such an intrinsic downcast of Address to one of its subclasses named USAddress.
*
* todo (6.0) : maybe "localized downcast" is a better term here, rather than "incidental downcast".
* tbh, "incidental" makes me think more of Hibernate's "implicit downcast" feature.
*
* @author Steve Ebersole
*/
public class TreatedNavigableReference extends AbstractSqmNavigableReference implements SqmNavigableReference,
SqmNavigableSourceReference {
private final SqmNavigableReference baseBinding;
private final EntityValuedExpressableType subclassIndicator;
public TreatedNavigableReference(SqmNavigableReference baseBinding, EntityValuedExpressableType subclassIndicator) {
this.baseBinding = baseBinding;
this.subclassIndicator = subclassIndicator;
baseBinding.addDowncast( new SqmDowncast( subclassIndicator ) );
}
public EntityValuedExpressableType getSubclassIndicator() {
return subclassIndicator;
}
@Override
public Navigable getReferencedNavigable() {
return subclassIndicator;
}
@Override
public SqmNavigableSourceReference getSourceReference() {
return baseBinding.getSourceReference();
}
@Override
public NavigablePath getNavigablePath() {
return baseBinding.getNavigablePath();
}
@Override
public ExpressableType getExpressionType() {
return subclassIndicator;
}
@Override
public ExpressableType getInferableType() {
return getExpressionType();
}
@Override
public <T> T accept(SemanticQueryWalker<T> walker) {
return baseBinding.accept( walker );
}
@Override
public String asLoggableText() {
return "TREAT( " + baseBinding.asLoggableText() + " AS " + subclassIndicator.asLoggableText() + " )";
}
@Override
public SqmFrom getExportedFromElement() {
return ( (SqmFromExporter) baseBinding ).getExportedFromElement();
}
@Override
public void injectExportedFromElement(SqmFrom sqmFrom) {
( (SqmFromExporter) baseBinding ).injectExportedFromElement( sqmFrom );
}
}