/* * Hibernate, Relational Persistence for Idiomatic Java * * License: Apache License, Version 2.0 * See the LICENSE file in the root directory or visit http://www.apache.org/licenses/LICENSE-2.0 */ package org.hibernate.test.sqm.parser.criteria.tree; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import javax.persistence.criteria.AbstractQuery; import javax.persistence.criteria.ParameterExpression; import javax.persistence.criteria.Root; import javax.persistence.criteria.Selection; import javax.persistence.criteria.Subquery; import javax.persistence.metamodel.EntityType; import org.hibernate.orm.persister.entity.spi.EntityPersister; import org.hibernate.query.sqm.NotYetImplementedException; import org.hibernate.query.sqm.produce.spi.criteria.JpaExpression; import org.hibernate.query.sqm.produce.spi.criteria.JpaOrder; import org.hibernate.query.sqm.produce.spi.criteria.JpaPredicate; import org.hibernate.query.sqm.produce.spi.criteria.JpaQuerySpec; import org.hibernate.query.sqm.produce.spi.criteria.JpaSubquery; import org.hibernate.query.sqm.produce.spi.criteria.from.JpaFromClause; import org.hibernate.query.sqm.produce.spi.criteria.select.JpaSelectClause; import org.hibernate.query.sqm.produce.spi.criteria.select.JpaSelection; import org.hibernate.test.sqm.parser.criteria.tree.path.RootImpl; /** * Models basic query structure. Used as a delegate in implementing both * {@link javax.persistence.criteria.CriteriaQuery} and * {@link Subquery}. * <p/> * Note the <tt>ORDER BY</tt> specs are neglected here. That's because it is not valid * for a subquery to define an <tt>ORDER BY</tt> clause. So we just handle them on the * root query directly... * * @author Steve Ebersole */ public class JpaQuerySpecImpl<T> implements JpaQuerySpec<T>, Serializable { private final AbstractQuery<T> owner; private final CriteriaBuilderImpl criteriaBuilder; private final boolean isSubQuery; public JpaQuerySpecImpl(AbstractQuery<T> owner, CriteriaBuilderImpl criteriaBuilder) { this.owner = owner; this.criteriaBuilder = criteriaBuilder; this.isSubQuery = Subquery.class.isInstance( owner ); } private JpaSelectClauseImpl<T> jpaSelectClause = new JpaSelectClauseImpl<>(); private FromClauseImpl fromClause = new FromClauseImpl(); private JpaPredicate restriction; private List<JpaExpression<?>> groupings = Collections.emptyList(); private JpaPredicate having; private List<JpaOrder> jpaOrderByList; private List<JpaSubquery<?>> subqueries; // SELECTION ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ public boolean isDistinct() { return jpaSelectClause.isDistinct(); } public void setDistinct(boolean distinct) { jpaSelectClause.setDistinct( distinct ); } public Selection<? extends T> getSelection() { return jpaSelectClause.getSelection(); } public void setSelection(JpaSelection<? extends T> selection) { jpaSelectClause.setJpaSelection( selection ); } // ROOTS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @SuppressWarnings("unchecked") public <X> Root<X> from(Class<X> entityClass) { EntityPersister<X> persister = (EntityPersister<X>) criteriaBuilder.consumerContext() .getDomainMetamodel() .resolveEntityReference( entityClass ); if ( persister == null ) { throw new IllegalArgumentException( entityClass + " is not an entity" ); } return from( persister ); } private <X> Root<X> from(EntityPersister<X> entityType) { RootImpl<X> root = new RootImpl<X>( criteriaBuilder, entityType ); fromClause.addRoot( root ); return root; } @SuppressWarnings("unchecked") public <X> Root<X> from(String entityName) { EntityPersister<X> entityType = (EntityPersister<X>) criteriaBuilder.consumerContext() .getDomainMetamodel() .resolveEntityReference( entityName ); if ( entityType == null ) { throw new IllegalArgumentException( entityName + " is not an entity" ); } return from( entityType ); } public <X> Root<X> from(EntityType<X> entityType) { throw new NotYetImplementedException( ); // RootImpl<X> root = new RootImpl<X>( criteriaBuilder, entityType ); // roots.add( root ); // return root; } // CORRELATION ROOTS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // public void addCorrelationRoot(JpaFrom<?,?> jpaFrom) { // if ( !isSubQuery ) { // throw new IllegalStateException( "Query is not identified as sub-query" ); // } // if ( correlationRoots == null ) { // correlationRoots = new HashSet<>(); // } // correlationRoots.add( jpaFrom ); // } // // public Set<JpaAttributeJoin<?, ?>> collectCorrelatedJoins() { // if ( !isSubQuery ) { // throw new IllegalStateException( "Query is not identified as sub-query" ); // } // final Set<JpaAttributeJoin<?, ?>> correlatedJoins; // if ( correlationRoots != null ) { // correlatedJoins = new HashSet<>(); // for ( JpaFrom<?,?> correlationRoot : correlationRoots ) { // if (correlationRoot instanceof JpaAttributeJoin<?,?> && correlationRoot.isCorrelated()) { // correlatedJoins.add( (JpaAttributeJoin<?,?>) correlationRoot ); // } // correlationRoot.getJoins().forEach( // join -> correlatedJoins.add( (JpaAttributeJoin<?, ?>) join ) // ); // } // } // else { // correlatedJoins = Collections.emptySet(); // } // return correlatedJoins; // } @Override public JpaSelectClause getSelectClause() { return jpaSelectClause; } @Override public JpaFromClause getFromClause() { return fromClause; } public void clearOrderList() { if ( jpaOrderByList != null ) { jpaOrderByList.clear(); jpaOrderByList = null; } } public void addOrderBy(JpaOrder order) { if ( jpaOrderByList == null ) { jpaOrderByList = new ArrayList<>(); } jpaOrderByList.add( order ); } @Override public List<JpaOrder> getOrderList() { return jpaOrderByList == null ? Collections.emptyList() : Collections.unmodifiableList( jpaOrderByList ); } // RESTRICTIONS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ public JpaPredicate getRestriction() { return restriction; } public void setRestriction(JpaPredicate restriction) { this.restriction = restriction; } // GROUPINGS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ public List<JpaExpression<?>> getGroupings() { return groupings; } public void setGroupings(List<JpaExpression<?>> groupings) { this.groupings = groupings; } public void setGroupings(JpaExpression<?>... groupings) { if ( groupings != null && groupings.length > 0 ) { this.groupings = Arrays.asList( groupings ); } else { this.groupings = Collections.emptyList(); } } public JpaPredicate getHaving() { return having; } public void setHaving(JpaPredicate having) { this.having = having; } // SUB-QUERIES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ public List<JpaSubquery<?>> getSubqueries() { return subqueries; } public List<JpaSubquery<?>> internalGetSubqueries() { if ( subqueries == null ) { subqueries = new ArrayList<>(); } return subqueries; } public <U> Subquery<U> subquery(Class<U> subqueryType) { // CriteriaSubqueryImpl<U> subquery = new CriteriaSubqueryImpl<U>( criteriaBuilder, subqueryType, owner ); // internalGetSubqueries().add( subquery ); // return subquery; throw new NotYetImplementedException( ); } // PARAMETERS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ public Set<ParameterExpression<?>> collectParameters() { final Set<ParameterExpression<?>> parameters = new LinkedHashSet<ParameterExpression<?>>(); // final ParameterRegistry registry = new ParameterRegistry() { // public void registerParameter(ParameterExpression<?> parameter) { // parameters.add( parameter ); // } // }; // // ParameterContainer.Helper.possibleParameter(selection, registry); // ParameterContainer.Helper.possibleParameter(restriction, registry); // ParameterContainer.Helper.possibleParameter(having, registry); // if ( subqueries != null ) { // for ( Subquery subquery : subqueries ) { // ParameterContainer.Helper.possibleParameter(subquery, registry); // } // } // // // both group-by and having expressions can (though unlikely) contain parameters... // ParameterContainer.Helper.possibleParameter(having, registry); // if ( groupings != null ) { // for ( Expression<?> grouping : groupings ) { // ParameterContainer.Helper.possibleParameter(grouping, registry); // } // } // return parameters; } }