/*
 * Copyright (c) 2011, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2021 IBM Corporation. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Gordon Yorke - Initial development
//     10/01/2018: Will Dazey
//       - #253: Add support for embedded constructor results with CriteriaBuilder
package org.eclipse.persistence.internal.jpa.querydef;

import java.lang.reflect.Constructor;
import java.security.AccessController;
import java.util.*;

import jakarta.persistence.Tuple;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.Order;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import jakarta.persistence.criteria.Selection;
import jakarta.persistence.metamodel.Metamodel;
import jakarta.persistence.metamodel.Type.PersistenceType;

import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.internal.helper.BasicTypeHelperImpl;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl;
import org.eclipse.persistence.internal.jpa.metamodel.TypeImpl;
import org.eclipse.persistence.internal.localization.ExceptionLocalization;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedGetConstructorFor;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.ReadAllQuery;
import org.eclipse.persistence.queries.ReportQuery;

/**
 * <p>
 * <b>Purpose</b>: Contains the implementation of the CriteriaQuery interface of
 * the JPA criteria API.
 * <p>
 * <b>Description</b>: This is the container class for the components that
 * define a query.
 * <p>
 *
 * @see jakarta.persistence.criteria CriteriaQuery
 *
 * @author gyorke
 * @since EclipseLink 1.2
 */
public class CriteriaQueryImpl<T> extends AbstractQueryImpl<T> implements CriteriaQuery<T> {

    protected SelectionImpl<?> selection;
    protected List<Order> orderBy;

    protected Set<FromImpl> joins;

    public CriteriaQueryImpl(Metamodel metamodel, ResultType queryResult, Class result, CriteriaBuilderImpl queryBuilder) {
        super(metamodel, queryResult, queryBuilder, result);
    }

    /**
     * Specify the item that is to be returned in the query result. Replaces the
     * previously specified selection, if any.
     *
     * @param selection
     *            selection specifying the item that is to be returned in the
     *            query result
     * @return the modified query
     */
    @Override
    public CriteriaQuery<T> select(Selection<? extends T> selection) {
        this.selection = (SelectionImpl<? extends T>) selection;
        this.selection.findRootAndParameters(this);
        if (selection.isCompoundSelection()) {
            //bug 366386: validate that aliases are not reused
            if (this.selection.isCompoundSelection() && ((CompoundSelectionImpl)this.selection).getDuplicateAliasNames() != null) {
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage("jpa_criteriaapi_alias_reused",
                        new Object[] { ((CompoundSelectionImpl)this.selection).getDuplicateAliasNames() }));
            }
            if (selection.getJavaType().equals(Tuple.class)) {
                this.queryResult = ResultType.TUPLE;
                this.queryType = Tuple.class;
            } else if (((InternalSelection) selection).isConstructor()) {
                Selection[] selectArray = selection.getCompoundSelectionItems().toArray(new Selection[selection.getCompoundSelectionItems().size()]);
                populateAndSetConstructorSelection((ConstructorSelectionImpl)selection, this.selection.getJavaType(), selectArray);
                this.queryType = selection.getJavaType();
            } else {
                this.queryResult = ResultType.OBJECT_ARRAY;
                this.queryType = ClassConstants.AOBJECT;
            }
        } else {
            // Update query type only when it's not null in selection argument.
            Class queryType = selection.getJavaType();
            if (queryType != null) {
                this.queryType = queryType;
            }
            TypeImpl type = ((MetamodelImpl)this.metamodel).getType(this.queryType);
            if (type != null && type.getPersistenceType().equals(PersistenceType.ENTITY)) {
                this.queryResult = ResultType.ENTITY; // this will be a selection item in a report query
            } else {
                this.queryResult = ResultType.OTHER;
            }
        }
        return this;
    }

    /**
     * Specify the items that are to be returned in the query result. Replaces
     * the previously specified selection(s), if any.
     *
     * The type of the result of the query execution depends on the
     * specification of the criteria query object as well as the arguments to
     * the multiselect method as follows:
     *
     * If the type of the criteria query is CriteriaQuery&lt;Tuple&gt;, a Tuple object
     * corresponding to the arguments of the multiselect method will be
     * instantiated and returned for each row that results from the query
     * execution.
     *
     * If the type of the criteria query is CriteriaQuery&lt;X&gt; for some
     * user-defined class X, then the arguments to the multiselect method will
     * be passed to the X constructor and an instance of type X will be returned
     * for each row. The IllegalStateException will be thrown if a constructor
     * for the given argument types does not exist.
     *
     * If the type of the criteria query is CriteriaQuery&lt;X[]&gt; for some class X,
     * an instance of type X[] will be returned for each row. The elements of
     * the array will correspond to the arguments of the multiselect method. The
     * IllegalStateException will be thrown if the arguments to the multiselect
     * method are not of type X.
     *
     * If the type of the criteria query is CriteriaQuery&lt;Object&gt;, and only a
     * single argument is passed to the multiselect method, an instance of type
     * Object will be returned for each row.
     *
     * If the type of the criteria query is CriteriaQuery&lt;Object&gt;, and more than
     * one argument is passed to the multiselect method, an instance of type
     * Object[] will be instantiated and returned for each row. The elements of
     * the array will correspond to the arguments to the multiselect method.
     *
     * @param selections
     *            expressions specifying the items that are to be returned in
     *            the query result
     * @return the modified query
     */
    @Override
    public CriteriaQuery<T> multiselect(Selection<?>... selections) {
        if (selections == null || selections.length == 0) {
            this.selection = null;
            return this;
        }
        for (Selection select : selections) {
            ((SelectionImpl)select).findRootAndParameters(this);
        }
        if (this.queryResult == ResultType.CONSTRUCTOR) {
            populateAndSetConstructorSelection(null, this.queryType, selections);
        } else if (this.queryResult.equals(ResultType.ENTITY)) {
            if (selections.length == 1 && selections[0].getJavaType().equals(this.queryType)) {
                this.selection = (SelectionImpl<?>) selections[0];
            } else {
                try {
                    populateAndSetConstructorSelection(null, this.queryType, selections);//throws IllegalArgumentException if it doesn't exist
                } catch(IllegalArgumentException constructorDoesNotExist){
                    this.queryResult = ResultType.PARTIAL;
                    this.selection = new CompoundSelectionImpl(this.queryType, selections);
                }
            }
        } else if (this.queryResult.equals(ResultType.TUPLE)) {
            this.selection = new CompoundSelectionImpl(this.queryType, selections);
        } else if (this.queryResult.equals(ResultType.OTHER)) {
            if (selections.length == 1 && selections[0].getJavaType().equals(this.queryType)) {
                this.selection = (SelectionImpl<?>) selections[0];
            } else {
                if (!BasicTypeHelperImpl.getInstance().isDateClass(this.queryType)) {
                    throw new IllegalArgumentException(ExceptionLocalization.buildMessage("MULTIPLE_SELECTIONS_PASSED_TO_QUERY_WITH_PRIMITIVE_RESULT"));
                }
                populateAndSetConstructorSelection(null, this.queryType, selections);
            }
        } else { // unknown
            this.selection = new CompoundSelectionImpl(this.queryType, selections);
        }
        //bug 366386: validate that aliases are not reused
        if (this.selection.isCompoundSelection() && ((CompoundSelectionImpl)this.selection).getDuplicateAliasNames() != null) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("jpa_criteriaapi_alias_reused",
                    new Object[] { ((CompoundSelectionImpl)this.selection).getDuplicateAliasNames() }));
        }
        return this;
    }

    /**
     * Specify the items that are to be returned in the query result. Replaces
     * the previously specified selection(s), if any.
     *
     * The type of the result of the query execution depends on the
     * specification of the criteria query object as well as the arguments to
     * the multiselect method as follows:
     *
     * If the type of the criteria query is CriteriaQuery&lt;Tuple&gt;, a Tuple object
     * corresponding to the items in the selection list passed to the
     * multiselect method will be instantiated and returned for each row that
     * results from the query execution.
     *
     * If the type of the criteria query is CriteriaQuery&lt;X&gt; for some
     * user-defined class X, then the items in the selection list passed to the
     * multiselect method will be passed to the X constructor and an instance of
     * type X will be returned for each row. The IllegalStateException will be
     * thrown if a constructor for the given argument types does not exist.
     *
     * If the type of the criteria query is CriteriaQuery&lt;X[]&gt; for some class X,
     * an instance of type X[] will be returned for each row. The elements of
     * the array will correspond to the items in the selection list passed to
     * the multiselect method. The IllegalStateException will be thrown if the
     * elements in the selection list passed to the multiselect method are not
     * of type X.
     *
     * If the type of the criteria query is CriteriaQuery&lt;Object&gt;, and the
     * selection list passed to the multiselect method contains only a single
     * item, an instance of type Object will be returned for each row.
     *
     * If the type of the criteria query is CriteriaQuery&lt;Object&gt;, and the
     * selection list passed to the multiselect method contains more than one
     * item, an instance of type Object[] will be instantiated and returned for
     * each row. The elements of the array will correspond to the items in the
     * selection list passed to the multiselect method.
     *
     * @param selectionList
     *            list of expressions specifying the items that to be are
     *            returned in the query result
     * @return the modified query
     */
    @Override
    public CriteriaQuery<T> multiselect(List<Selection<?>> selectionList) {
        if (selectionList == null) {
            this.selection = null;
            return this;
        }
        return this.multiselect(selectionList.toArray(new Selection[selectionList.size()]));
    }

    // override the return type only:
    /**
     * Modify the query to restrict the query result according to the specified
     * boolean expression. Replaces the previously added restriction(s), if any.
     * This method only overrides the return type of the corresponding
     * AbstractQuery method.
     *
     * @param restriction
     *            a simple or compound boolean expression
     * @return the modified query
     */
    @Override
    public CriteriaQuery<T> where(Expression<Boolean> restriction) {
        return (CriteriaQuery<T>) super.where(restriction);
    }

    /**
     * Modify the query to restrict the query result according to the
     * conjunction of the specified restriction predicates. Replaces the
     * previously added restriction(s), if any. If no restrictions are
     * specified, any previously added restrictions are simply removed. This
     * method only overrides the return type of the corresponding AbstractQuery
     * method.
     *
     * @param restrictions
     *            zero or more restriction predicates
     * @return the modified query
     */
    @Override
    public CriteriaQuery<T> where(Predicate... restrictions) {
        return (CriteriaQuery<T>) super.where(restrictions);
    }

    /**
     * Specify the expressions that are used to form groups over the query
     * results. Replaces the previous specified grouping expressions, if any. If
     * no grouping expressions are specified, any previously added grouping
     * expressions are simply removed. This method only overrides the return
     * type of the corresponding AbstractQuery method.
     *
     * @param grouping
     *            zero or more grouping expressions
     * @return the modified query
     */
    @Override
    public CriteriaQuery<T> groupBy(Expression<?>... grouping) {
        super.groupBy(grouping);
        return this;
    }

    /**
     * Specify the expressions that are used to form groups over the query
     * results. Replaces the previous specified grouping expressions, if any. If
     * no grouping expressions are specified, any previously added grouping
     * expressions are simply removed. This method only overrides the return
     * type of the corresponding AbstractQuery method.
     *
     * @param grouping
     *            list of zero or more grouping expressions
     * @return the modified query
     */
    @Override
    public CriteriaQuery<T> groupBy(List<Expression<?>> grouping) {
        super.groupBy(grouping);
        return this;
    }

    /**
     * Specify a restriction over the groups of the query. Replaces the previous
     * having restriction(s), if any. This method only overrides the return type
     * of the corresponding AbstractQuery method.
     *
     * @param restriction
     *            a simple or compound boolean expression
     * @return the modified query
     */
    @Override
    public CriteriaQuery<T> having(Expression<Boolean> restriction) {
        super.having(restriction);
        return this;
    }

    /**
     * Specify restrictions over the groups of the query according the
     * conjunction of the specified restriction predicates. Replaces the
     * previously added restriction(s), if any. If no restrictions are
     * specified, any previously added restrictions are simply removed. This
     * method only overrides the return type of the corresponding AbstractQuery
     * method.
     *
     * @param restrictions
     *            zero or more restriction predicates
     * @return the modified query
     */
    @Override
    public CriteriaQuery<T> having(Predicate... restrictions) {
        super.having(restrictions);
        return this;
    }

    /**
     * Specify the ordering expressions that are used to order the query
     * results. Replaces the previous ordering expressions, if any. If no
     * ordering expressions are specified, the previous ordering, if any, is
     * simply removed, and results will be returned in no particular order. The
     * left-to-right sequence of the ordering expressions determines the
     * precedence, whereby the leftmost has highest precedence.
     *
     * @param o
     *            zero or more ordering expressions
     * @return the modified query.
     */
    @Override
    public CriteriaQuery<T> orderBy(Order... o) {
        this.orderBy = new ArrayList();
        for (Order order : o) {
            this.orderBy.add(order);
        }
        return this;
    }

    /**
     * Specify the ordering expressions that are used to order the query
     * results. Replaces the previous ordering expressions, if any. If no
     * ordering expressions are specified, the previous ordering, if any, is
     * simply removed, and results will be returned in no particular order. The
     * order of the ordering expressions in the list determines the precedence,
     * whereby the first element in the list has highest precedence.
     *
     * @param o
     *            list of zero or more ordering expressions
     * @return the modified query.
     */
    @Override
    public CriteriaQuery<T> orderBy(List<Order> o) {
        this.orderBy = o;
        return this;
    }

    /**
     * This method will set this queryImpl's selection to a ConstructorSelectionImpl, creating a new
     * instance or populating the one passed in as necessary.
     * Throws IllegalArgumentException if a constructor taking arguments represented
     * by the selections array doesn't exist for the given class.
     *
     * Also sets the query result to ResultType.CONSTRUCTOR
     *
     * @param class1
     * @param selections
     * @throws IllegalArgumentException
     */
    public void populateAndSetConstructorSelection(ConstructorSelectionImpl constructorSelection, Class<?> class1, Selection<?>... selections) throws IllegalArgumentException{
        Class[] constructorArgs = new Class[selections.length];
        int count = 0;
        for (Selection select : selections) {
            if(select instanceof ConstructorSelectionImpl) {
                ConstructorSelectionImpl constructorSelect = (ConstructorSelectionImpl)select;
                Selection[] selectArray = constructorSelect.getCompoundSelectionItems().toArray(new Selection[constructorSelect.getCompoundSelectionItems().size()]);
                populateAndSetConstructorSelection(constructorSelect, constructorSelect.getJavaType(), selectArray);
            }
            constructorArgs[count++] = select.getJavaType();
        }
        Constructor constructor = null;
        try {
            if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
                constructor = AccessController.doPrivileged(new PrivilegedGetConstructorFor(class1, constructorArgs, false));
            } else {
                constructor = PrivilegedAccessHelper.getConstructorFor(class1, constructorArgs, false);
            }
            if (constructorSelection == null){
                constructorSelection = new ConstructorSelectionImpl(class1, selections);
            }
            this.queryResult = ResultType.CONSTRUCTOR;
            constructorSelection.setConstructor(constructor);
            constructorSelection.setConstructorArgTypes(constructorArgs);
            this.selection = constructorSelection;
        } catch (Exception e){
            //PrivilegedActionException and NoSuchMethodException are possible
            Object[] params = new Object[1];
            params[0] = this.queryType;
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("criteria_no_constructor_found", params), e);
        }
    }

    /**
     * Specify whether duplicate query results will be eliminated. A true value
     * will cause duplicates to be eliminated. A false value will cause
     * duplicates to be retained. If distinct has not been specified, duplicate
     * results must be retained. This method only overrides the return type of
     * the corresponding AbstractQuery method.
     *
     * @param distinct
     *            boolean value specifying whether duplicate results must be
     *            eliminated from the query result or whether they must be
     *            retained
     * @return the modified query.
     */
    @Override
    public CriteriaQuery<T> distinct(boolean distinct) {
        super.distinct(distinct);
        return this;
    }

    @Override
    public void addJoin(FromImpl from) {
        if (this.joins == null) {
            this.joins = new LinkedHashSet<FromImpl>();
        }
        this.joins.add(from);
    }

    @Override
    protected DatabaseQuery getDatabaseQuery() {
        ObjectLevelReadQuery query = null;
        if (this.selection == null || !this.selection.isCompoundSelection()) {
            query = createSimpleQuery();
        } else {
            query = createCompoundQuery();
        }
        return query;
    }

    /**
     * Return the ordering expressions in order of precedence.
     *
     * @return the list of ordering expressions
     */
    @Override
    public List<Order> getOrderList() {
        return this.orderBy;
    }

    /**
     * Return the selection item of the query. This will correspond to the query
     * type.
     *
     * @return the selection item of the query
     */
    @Override
    public Selection<T> getSelection() {
        return (Selection<T>) this.selection;
    }

    /**
     * Translates from the criteria query to a EclipseLink Database Query.
     */
    @SuppressWarnings("deprecation")
    protected ObjectLevelReadQuery createCompoundQuery() {
        ObjectLevelReadQuery query = null;
        if (this.queryResult == ResultType.UNKNOWN) {
            if (this.selection.isConstructor()) {
                this.queryResult = ResultType.CONSTRUCTOR;
            } else if (this.selection.getJavaType().equals(Tuple.class)) {
                this.queryResult = ResultType.TUPLE;
            } else {
                this.queryResult = ResultType.OBJECT_ARRAY;
            }
        }

        if (this.queryResult.equals(ResultType.PARTIAL)) {
            ReadAllQuery raq = new ReadAllQuery(this.queryType);
            for (Selection selection : this.selection.getCompoundSelectionItems()) {
                raq.addPartialAttribute(((SelectionImpl) selection).currentNode);
            }
            raq.setExpressionBuilder(((InternalSelection) this.selection.getCompoundSelectionItems().get(0)).getCurrentNode().getBuilder());
            query = raq;
        } else {
            ReportQuery reportQuery = null;
            if (this.queryResult.equals(ResultType.CONSTRUCTOR) || this.queryResult.equals(ResultType.OTHER)) {
                // other is also a constructor type if multi-select was called.
                // with a type other than the query type.
                reportQuery = new ReportQuery();
                reportQuery.addConstructorReportItem(((ConstructorSelectionImpl) this.selection).translate());
                reportQuery.setShouldReturnSingleAttribute(true);
            } else {
                if (this.queryResult.equals(ResultType.TUPLE)) {
                    reportQuery = new TupleQuery(this.selection == null ? new ArrayList() : this.selection.getCompoundSelectionItems());
                } else {
                    reportQuery = new ReportQuery();
                    reportQuery.setShouldReturnWithoutReportQueryResult(true);
                }
                reportQuery.setExpressionBuilder(((InternalSelection) this.selection.getCompoundSelectionItems().get(0)).getCurrentNode().getBuilder());
                for (Selection nested : this.selection.getCompoundSelectionItems()) {
                    if (((SelectionImpl) nested).isConstructor()) {
                        reportQuery.addConstructorReportItem(((ConstructorSelectionImpl) nested).translate());
                    } else if (nested.isCompoundSelection()) {
                        throw new IllegalStateException(ExceptionLocalization.buildMessage("NESTED_COMPOUND_SELECTION_OTHER_THAN_CONSTRUCTOR_NOT_SUPPORTED"));
                    } else {
                        if (((InternalSelection) nested).isFrom()) {
                            reportQuery.addItem(nested.getAlias(), ((SelectionImpl) nested).getCurrentNode(), ((FromImpl) nested).findJoinFetches());
                        } else if (((InternalExpression) nested).isCompoundExpression() && ((FunctionExpressionImpl) nested).getOperation() == CriteriaBuilderImpl.SIZE) {
                            //selecting size not all databases support subselect in select clause so convert to count/groupby
                            PathImpl collectionExpression = (PathImpl) ((FunctionExpressionImpl) nested).getChildExpressions().get(0);
                            ExpressionImpl fromExpression = (ExpressionImpl) collectionExpression.getParentPath();
                            reportQuery.addAttribute(nested.getAlias(), collectionExpression.getCurrentNode().count(), ClassConstants.INTEGER);
                            reportQuery.addGrouping(fromExpression.getCurrentNode());
                        } else {
                            reportQuery.addAttribute(nested.getAlias(), ((SelectionImpl) nested).getCurrentNode(), nested.getJavaType());
                        }
                    }
                }
            }

            ExpressionBuilder builder = null;
            Class<?> queryClazz = null;
            // First check the WHERE clause
            if(this.where != null && ((InternalSelection) this.where).getCurrentNode() != null) {
                builder = ((InternalSelection) this.where).getCurrentNode().getBuilder();
                queryClazz = builder.getQueryClass();
            }
            // Check all the SELECTION items next
            if(queryClazz == null && this.selection != null) {
                for(Selection<?> s : this.selection.getCompoundSelectionItems()) {
                    if(((InternalSelection) s).getCurrentNode() != null ) {
                        builder = ((InternalSelection) s).getCurrentNode().getBuilder();
                        queryClazz = builder.getQueryClass();
                        if(queryClazz != null) {
                            break;
                        }
                    }
                }
            }
            // Fallback on the root
            if(queryClazz == null && this.roots != null) {
                for(Root<?> r : this.roots) {
                    if(((RootImpl<?>) r).getCurrentNode() != null ) {
                        builder = ((RootImpl<?>) r).getCurrentNode().getBuilder();
                        queryClazz = builder.getQueryClass();
                        if(queryClazz != null) {
                            break;
                        }
                    }
                }
            }
            reportQuery.setExpressionBuilder(builder);
            reportQuery.setReferenceClass(queryClazz);

            query = reportQuery;
            if (this.groupBy != null && !this.groupBy.isEmpty()) {
                for (Expression<?> exp : this.groupBy) {
                    reportQuery.addGrouping(((InternalSelection) exp).getCurrentNode());
                }
            }
            if (this.havingClause != null) {
                reportQuery.setHavingExpression(((InternalSelection) this.havingClause).getCurrentNode());
            }
        }
        return query;
    }

    protected ObjectLevelReadQuery createSimpleQuery() {
        ObjectLevelReadQuery query = null;

        if (this.queryResult == ResultType.UNKNOWN) {
            // unknown type so let's figure this out.
            if (selection == null) {
                if (this.roots != null && !this.roots.isEmpty()) {
                    this.selection = (SelectionImpl<?>) this.roots.iterator().next();
                    query = new ReadAllQuery(((FromImpl) this.selection).getJavaType());
                    List<org.eclipse.persistence.expressions.Expression> list = ((FromImpl) this.roots.iterator().next()).findJoinFetches();
                    for (org.eclipse.persistence.expressions.Expression fetch : list) {
                        query.addJoinedAttribute(fetch);
                    }
                    if (!list.isEmpty()) {
                        query.setExpressionBuilder(list.get(0).getBuilder());
                    }
                } else if (this.roots == null || this.roots.isEmpty()) {
                    throw new IllegalArgumentException(ExceptionLocalization.buildMessage("CRITERIA_NO_ROOT_FOR_COMPOUND_QUERY"));
                }

            } else {
                // Selection is not null set type to selection
                TypeImpl type = ((MetamodelImpl)this.metamodel).getType(selection.getJavaType());
                if (type != null && type.getPersistenceType().equals(PersistenceType.ENTITY)) {
                    query = new ReadAllQuery(type.getJavaType());
                    List<org.eclipse.persistence.expressions.Expression> list = ((FromImpl) this.roots.iterator().next()).findJoinFetches();
                    for (org.eclipse.persistence.expressions.Expression fetch : list) {
                        query.addJoinedAttribute(fetch);
                    }
                    query.setExpressionBuilder(((InternalSelection)selection).getCurrentNode().getBuilder());

                } else {
                    query = new ReportQuery();
                    query.setReferenceClass(this.selection.getCurrentNode().getBuilder().getQueryClass());
                    if (!this.selection.isCompoundSelection() && ((InternalExpression) this.selection).isCompoundExpression()) {
                        if (((FunctionExpressionImpl) this.selection).getOperation() == CriteriaBuilderImpl.SIZE) {
                            //selecting size not all databases support subselect in select clause so convert to count/groupby
                            PathImpl collectionExpression = (PathImpl) ((FunctionExpressionImpl) this.selection).getChildExpressions().get(0);
                            ExpressionImpl fromExpression = (ExpressionImpl) collectionExpression.getParentPath();
                            ((ReportQuery) query).addAttribute(this.selection.getAlias(), collectionExpression.getCurrentNode().count(), ClassConstants.INTEGER);
                            ((ReportQuery) query).addGrouping(fromExpression.getCurrentNode());
                        }
                        ((ReportQuery) query).addAttribute(this.selection.getAlias(), this.selection.getCurrentNode(), this.selection.getJavaType());

                    } else {
                        ((ReportQuery) query).addItem(this.selection.getAlias(), this.selection.getCurrentNode());
                        ((ReportQuery) query).setShouldReturnSingleAttribute(true);
                    }
                }
            }
        } else if (this.queryResult.equals(ResultType.ENTITY)) {

            if (this.selection != null && (!((InternalSelection) this.selection).isRoot())) {
                query = new ReportQuery();
                query.setReferenceClass(this.queryType);
                ((ReportQuery) query).addItem(this.selection.getAlias(), this.selection.getCurrentNode(), ((FromImpl) this.selection).findJoinFetches());
                ((ReportQuery) query).setShouldReturnSingleAttribute(true);
            } else {
                query = new ReadAllQuery(this.queryType);
                if (this.roots != null && !this.roots.isEmpty()) {
                    List<org.eclipse.persistence.expressions.Expression> list = ((FromImpl) this.roots.iterator().next()).findJoinFetches();
                    if (!list.isEmpty()) {
                        query.setExpressionBuilder(list.get(0).getBuilder()); // set the builder to one of the fetches bases.
                    }
                    for (org.eclipse.persistence.expressions.Expression fetch : list) {
                        query.addJoinedAttribute(fetch);
                    }
                }
                if (selection != null) {
                    query.setExpressionBuilder(this.selection.currentNode.getBuilder());
                }
            }
        } else {
            ReportQuery reportQuery = null;
            if (this.queryResult.equals(ResultType.TUPLE)) {
                List list = new ArrayList();
                list.add(this.selection);
                reportQuery = new TupleQuery(list);
            } else {
                reportQuery = new ReportQuery();
                reportQuery.setShouldReturnWithoutReportQueryResult(true);
            }
            if (this.selection != null) {
                if (!this.selection.isCompoundSelection() && ((InternalExpression)this.selection).isCompoundExpression()){
                    if(((FunctionExpressionImpl)this.selection).getOperation() == CriteriaBuilderImpl.SIZE){
                    //selecting size not all databases support subselect in select clause so convert to count/groupby
                    PathImpl collectionExpression = (PathImpl) ((FunctionExpressionImpl)this.selection).getChildExpressions().get(0);
                    ExpressionImpl fromExpression = (ExpressionImpl) collectionExpression.getParentPath();
                    reportQuery.addAttribute(this.selection.getAlias(), collectionExpression.getCurrentNode().count(), ClassConstants.INTEGER);
                    reportQuery.addGrouping(fromExpression.getCurrentNode());
                }else{
                    reportQuery.addAttribute(this.selection.getAlias(), this.selection.getCurrentNode(), this.selection.getJavaType());

                }}else{
                if (((InternalSelection) selection).isFrom()) {
                    reportQuery.addItem(selection.getAlias(), selection.getCurrentNode(), ((FromImpl) selection).findJoinFetches());
                } else {
                    reportQuery.addAttribute(selection.getAlias(), selection.getCurrentNode(), selection.getJavaType());
                }}
                reportQuery.setReferenceClass(((InternalSelection) this.selection).getCurrentNode().getBuilder().getQueryClass());
                reportQuery.setExpressionBuilder(((InternalSelection) this.selection).getCurrentNode().getBuilder());
            }
            query = reportQuery;
            if (this.groupBy != null && !this.groupBy.isEmpty()) {
                for (Expression<?> exp : this.groupBy) {
                    reportQuery.addGrouping(((InternalSelection) exp).getCurrentNode());
                }
            }
            if (this.havingClause != null) {
                reportQuery.setHavingExpression(((InternalSelection) this.havingClause).getCurrentNode());
            }
        }
        if (query.getReferenceClass() == null){
            if (this.where != null && ((InternalSelection) this.where).getCurrentNode() != null && ((InternalSelection) this.where).getCurrentNode().getBuilder() != null && ((InternalSelection) this.where).getCurrentNode().getBuilder().getQueryClass() != null) {
                query.setReferenceClass(((InternalSelection) this.where).getCurrentNode().getBuilder().getQueryClass());
            } else if (roots != null && ! roots.isEmpty()){
                Root root = this.getRoots().iterator().next();
                query.setReferenceClass(root.getJavaType());
            }
        }

        if (selection == null) {
            //the builder in the where clause  may not be the correct builder for this query.  Search for a root that matches the query type.
            if (roots != null && ! roots.isEmpty()){
                for (Root root : this.getRoots()){
                    if (root.getJavaType().equals(this.queryType)){
                        query.setExpressionBuilder(((RootImpl) root).getCurrentNode().getBuilder());
                        break;
                    }
                }
            }
        }

        return query;
    }

    /**
     * Translates from the criteria query to a EclipseLink Database Query.
     */
    @Override
    public DatabaseQuery translate() {
        ObjectLevelReadQuery query = (ObjectLevelReadQuery)super.translate();

        for (Iterator iterator = this.getRoots().iterator(); iterator.hasNext();) {
            findJoins((FromImpl) iterator.next());
        }

        if (this.joins != null && !joins.isEmpty()) {
            for (FromImpl join : this.joins) {
                query.addNonFetchJoinedAttribute(((InternalSelection) join).getCurrentNode());
            }
        }
        if (this.distinct) {
            query.setDistinctState(ObjectLevelReadQuery.USE_DISTINCT);
        } else {
            query.setDistinctState(ObjectLevelReadQuery.DONT_USE_DISTINCT);
            if (query.hasJoining()) {
                query.setShouldFilterDuplicates(false);
            }
        }
        if (this.orderBy != null && !this.orderBy.isEmpty()) {
            for (Order order : this.orderBy) {
                OrderImpl orderImpl = (OrderImpl) order;
                org.eclipse.persistence.expressions.Expression orderExp = ((ExpressionImpl) orderImpl.getExpression()).getCurrentNode();
                if (orderImpl.isAscending()) {
                    orderExp = orderExp.ascending();
                } else {
                    orderExp = orderExp.descending();
                }
                query.addOrdering(orderExp);
            }
        }

        return query;
    }

}
