/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @author tags or express
* copyright attribution statements applied by the authors. All
* third-party contributions are distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.ejb.criteria;
import java.io.Serializable;
import java.util.List;
import java.util.Set;
import javax.persistence.criteria.AbstractQuery;
import javax.persistence.criteria.CollectionJoin;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.ListJoin;
import javax.persistence.criteria.MapJoin;
import javax.persistence.criteria.ParameterExpression;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.persistence.criteria.SetJoin;
import javax.persistence.criteria.Subquery;
import javax.persistence.metamodel.EntityType;
import org.hibernate.ejb.criteria.expression.ExpressionImpl;
import org.hibernate.ejb.criteria.path.RootImpl;
/**
* The Hibernate implementation of the JPA {@link Subquery} contract. Mostlty a set of delegation to its internal
* {@link QueryStructure}.
*
* @author Steve Ebersole
*/
public class CriteriaSubqueryImpl<T> extends ExpressionImpl<T> implements Subquery<T>, Serializable {
private final AbstractQuery<?> parent;
private final QueryStructure<T> queryStructure;
public CriteriaSubqueryImpl(
CriteriaBuilderImpl criteriaBuilder,
Class<T> javaType,
AbstractQuery<?> parent) {
super( criteriaBuilder, javaType);
this.parent = parent;
this.queryStructure = new QueryStructure<T>( this, criteriaBuilder );
}
/**
* {@inheritDoc}
*/
public AbstractQuery<?> getParent() {
return parent;
}
/**
* {@inheritDoc}
*/
public void registerParameters(ParameterRegistry registry) {
for ( ParameterExpression param : queryStructure.getParameters() ) {
registry.registerParameter( param );
}
}
/**
* {@inheritDoc}
*/
public Class<T> getResultType() {
return getJavaType();
}
// ROOTS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* {@inheritDoc}
*/
public Set<Root<?>> getRoots() {
return queryStructure.getRoots();
}
/**
* {@inheritDoc}
*/
public <X> Root<X> from(EntityType<X> entityType) {
return queryStructure.from( entityType );
}
/**
* {@inheritDoc}
*/
public <X> Root<X> from(Class<X> entityClass) {
return queryStructure.from( entityClass );
}
// SELECTION ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public Subquery<T> distinct(boolean applyDistinction) {
queryStructure.setDistinct( applyDistinction );
return this;
}
public boolean isDistinct() {
return queryStructure.isDistinct();
}
public Expression<T> getSelection() {
return (Expression<T>) queryStructure.getSelection();
}
public Subquery<T> select(Expression<T> expression) {
queryStructure.setSelection( expression );
return this;
}
// RESTRICTION ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* {@inheritDoc}
*/
public Predicate getRestriction() {
return queryStructure.getRestriction();
}
/**
* {@inheritDoc}
*/
public Subquery<T> where(Expression<Boolean> expression) {
queryStructure.setRestriction( criteriaBuilder().wrap( expression ) );
return this;
}
/**
* {@inheritDoc}
*/
public Subquery<T> where(Predicate... predicates) {
// TODO : assuming this should be a conjuntion, but the spec does not say specifically...
queryStructure.setRestriction( criteriaBuilder().and( predicates ) );
return this;
}
// GROUPING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* {@inheritDoc}
*/
public List<Expression<?>> getGroupList() {
return queryStructure.getGroupings();
}
/**
* {@inheritDoc}
*/
public Subquery<T> groupBy(Expression<?>... groupings) {
queryStructure.setGroupings( groupings );
return this;
}
/**
* {@inheritDoc}
*/
public Subquery<T> groupBy(List<Expression<?>> groupings) {
queryStructure.setGroupings( groupings );
return this;
}
/**
* {@inheritDoc}
*/
public Predicate getGroupRestriction() {
return queryStructure.getHaving();
}
/**
* {@inheritDoc}
*/
public Subquery<T> having(Expression<Boolean> expression) {
queryStructure.setHaving( criteriaBuilder().wrap( expression ) );
return this;
}
/**
* {@inheritDoc}
*/
public Subquery<T> having(Predicate... predicates) {
queryStructure.setHaving( criteriaBuilder().and( predicates ) );
return this;
}
// CORRELATIONS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* {@inheritDoc}
*/
public Set<Join<?, ?>> getCorrelatedJoins() {
return queryStructure.collectCorrelatedJoins();
}
/**
* {@inheritDoc}
*/
public <Y> Root<Y> correlate(Root<Y> source) {
final RootImpl<Y> correlation = ( ( RootImpl<Y> ) source ).correlateTo( this );
queryStructure.addCorrelationRoot( correlation );
return correlation;
}
/**
* {@inheritDoc}
*/
public <X, Y> Join<X, Y> correlate(Join<X, Y> source) {
final JoinImplementor<X,Y> correlation = ( (JoinImplementor<X,Y>) source ).correlateTo( this );
queryStructure.addCorrelationRoot( correlation );
return correlation;
}
/**
* {@inheritDoc}
*/
public <X, Y> CollectionJoin<X, Y> correlate(CollectionJoin<X, Y> source) {
final CollectionJoinImplementor<X,Y> correlation = ( (CollectionJoinImplementor<X,Y>) source ).correlateTo( this );
queryStructure.addCorrelationRoot( correlation );
return correlation;
}
/**
* {@inheritDoc}
*/
public <X, Y> SetJoin<X, Y> correlate(SetJoin<X, Y> source) {
final SetJoinImplementor<X,Y> correlation = ( (SetJoinImplementor<X,Y>) source ).correlateTo( this );
queryStructure.addCorrelationRoot( correlation );
return correlation;
}
/**
* {@inheritDoc}
*/
public <X, Y> ListJoin<X, Y> correlate(ListJoin<X, Y> source) {
final ListJoinImplementor<X,Y> correlation = ( (ListJoinImplementor<X,Y>) source ).correlateTo( this );
queryStructure.addCorrelationRoot( correlation );
return correlation;
}
/**
* {@inheritDoc}
*/
public <X, K, V> MapJoin<X, K, V> correlate(MapJoin<X, K, V> source) {
final MapJoinImplementor<X, K, V> correlation = ( (MapJoinImplementor<X, K, V>) source ).correlateTo( this );
queryStructure.addCorrelationRoot( correlation );
return correlation;
}
/**
* {@inheritDoc}
*/
public <U> Subquery<U> subquery(Class<U> subqueryType) {
return queryStructure.subquery( subqueryType );
}
public String render(CriteriaQueryCompiler.RenderingContext renderingContext) {
StringBuilder subqueryBuffer = new StringBuilder( "(" );
queryStructure.render( subqueryBuffer, renderingContext );
subqueryBuffer.append( ')' );
return subqueryBuffer.toString();
}
public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) {
throw new IllegalStateException( "Subquery cannot occur in select clause" );
}
}