/*
 * Copyright (c) 2006, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2006, 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:
//     Oracle - initial API and implementation
//
//     04/11/2017-2.6 Will Dazey
//       - 512386: Concat expression return type Boolean -> String
//     02/20/2018-2.7 Will Dazey
//       - 531062: Incorrect expression type created for CollectionExpression
//     05/11/2018-2.7 Will Dazey
//       - 534515: Incorrect return type set for CASE functions
//     IBM - Bug 537795: CASE THEN and ELSE scalar expression Constants should not be casted to CASE operand type
package org.eclipse.persistence.internal.jpa.jpql;

import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.expressions.ExpressionMath;
import org.eclipse.persistence.internal.expressions.ConstantExpression;
import org.eclipse.persistence.internal.expressions.DateConstantExpression;
import org.eclipse.persistence.internal.expressions.MapEntryExpression;
import org.eclipse.persistence.internal.expressions.ParameterExpression;
import org.eclipse.persistence.internal.queries.ReportItem;
import org.eclipse.persistence.jpa.jpql.ExpressionTools;
import org.eclipse.persistence.jpa.jpql.JPQLQueryDeclaration.Type;
import org.eclipse.persistence.jpa.jpql.LiteralType;
import org.eclipse.persistence.jpa.jpql.parser.AbsExpression;
import org.eclipse.persistence.jpa.jpql.parser.AbstractEclipseLinkExpressionVisitor;
import org.eclipse.persistence.jpa.jpql.parser.AbstractExpressionVisitor;
import org.eclipse.persistence.jpa.jpql.parser.AbstractPathExpression;
import org.eclipse.persistence.jpa.jpql.parser.AbstractSchemaName;
import org.eclipse.persistence.jpa.jpql.parser.AdditionExpression;
import org.eclipse.persistence.jpa.jpql.parser.AllOrAnyExpression;
import org.eclipse.persistence.jpa.jpql.parser.AndExpression;
import org.eclipse.persistence.jpa.jpql.parser.AnonymousExpressionVisitor;
import org.eclipse.persistence.jpa.jpql.parser.ArithmeticFactor;
import org.eclipse.persistence.jpa.jpql.parser.AsOfClause;
import org.eclipse.persistence.jpa.jpql.parser.AvgFunction;
import org.eclipse.persistence.jpa.jpql.parser.BadExpression;
import org.eclipse.persistence.jpa.jpql.parser.BetweenExpression;
import org.eclipse.persistence.jpa.jpql.parser.CaseExpression;
import org.eclipse.persistence.jpa.jpql.parser.CastExpression;
import org.eclipse.persistence.jpa.jpql.parser.CoalesceExpression;
import org.eclipse.persistence.jpa.jpql.parser.CollectionExpression;
import org.eclipse.persistence.jpa.jpql.parser.CollectionMemberDeclaration;
import org.eclipse.persistence.jpa.jpql.parser.CollectionMemberExpression;
import org.eclipse.persistence.jpa.jpql.parser.CollectionValuedPathExpression;
import org.eclipse.persistence.jpa.jpql.parser.ComparisonExpression;
import org.eclipse.persistence.jpa.jpql.parser.ConcatExpression;
import org.eclipse.persistence.jpa.jpql.parser.ConnectByClause;
import org.eclipse.persistence.jpa.jpql.parser.ConstructorExpression;
import org.eclipse.persistence.jpa.jpql.parser.CountFunction;
import org.eclipse.persistence.jpa.jpql.parser.DatabaseType;
import org.eclipse.persistence.jpa.jpql.parser.DateTime;
import org.eclipse.persistence.jpa.jpql.parser.DeleteClause;
import org.eclipse.persistence.jpa.jpql.parser.DeleteStatement;
import org.eclipse.persistence.jpa.jpql.parser.DivisionExpression;
import org.eclipse.persistence.jpa.jpql.parser.EclipseLinkAnonymousExpressionVisitor;
import org.eclipse.persistence.jpa.jpql.parser.EclipseLinkExpressionVisitor;
import org.eclipse.persistence.jpa.jpql.parser.EmptyCollectionComparisonExpression;
import org.eclipse.persistence.jpa.jpql.parser.EntityTypeLiteral;
import org.eclipse.persistence.jpa.jpql.parser.EntryExpression;
import org.eclipse.persistence.jpa.jpql.parser.ExistsExpression;
import org.eclipse.persistence.jpa.jpql.parser.ExtractExpression;
import org.eclipse.persistence.jpa.jpql.parser.FromClause;
import org.eclipse.persistence.jpa.jpql.parser.FunctionExpression;
import org.eclipse.persistence.jpa.jpql.parser.GroupByClause;
import org.eclipse.persistence.jpa.jpql.parser.HavingClause;
import org.eclipse.persistence.jpa.jpql.parser.HierarchicalQueryClause;
import org.eclipse.persistence.jpa.jpql.parser.IdentificationVariable;
import org.eclipse.persistence.jpa.jpql.parser.IdentificationVariableDeclaration;
import org.eclipse.persistence.jpa.jpql.parser.InExpression;
import org.eclipse.persistence.jpa.jpql.parser.IndexExpression;
import org.eclipse.persistence.jpa.jpql.parser.InputParameter;
import org.eclipse.persistence.jpa.jpql.parser.JPQLExpression;
import org.eclipse.persistence.jpa.jpql.parser.Join;
import org.eclipse.persistence.jpa.jpql.parser.KeyExpression;
import org.eclipse.persistence.jpa.jpql.parser.KeywordExpression;
import org.eclipse.persistence.jpa.jpql.parser.LengthExpression;
import org.eclipse.persistence.jpa.jpql.parser.LikeExpression;
import org.eclipse.persistence.jpa.jpql.parser.LocateExpression;
import org.eclipse.persistence.jpa.jpql.parser.LowerExpression;
import org.eclipse.persistence.jpa.jpql.parser.MaxFunction;
import org.eclipse.persistence.jpa.jpql.parser.MinFunction;
import org.eclipse.persistence.jpa.jpql.parser.ModExpression;
import org.eclipse.persistence.jpa.jpql.parser.MultiplicationExpression;
import org.eclipse.persistence.jpa.jpql.parser.NotExpression;
import org.eclipse.persistence.jpa.jpql.parser.NullComparisonExpression;
import org.eclipse.persistence.jpa.jpql.parser.NullExpression;
import org.eclipse.persistence.jpa.jpql.parser.NullIfExpression;
import org.eclipse.persistence.jpa.jpql.parser.NumericLiteral;
import org.eclipse.persistence.jpa.jpql.parser.ObjectExpression;
import org.eclipse.persistence.jpa.jpql.parser.OnClause;
import org.eclipse.persistence.jpa.jpql.parser.OrExpression;
import org.eclipse.persistence.jpa.jpql.parser.OrderByClause;
import org.eclipse.persistence.jpa.jpql.parser.OrderByItem;
import org.eclipse.persistence.jpa.jpql.parser.OrderSiblingsByClause;
import org.eclipse.persistence.jpa.jpql.parser.RangeVariableDeclaration;
import org.eclipse.persistence.jpa.jpql.parser.RegexpExpression;
import org.eclipse.persistence.jpa.jpql.parser.ResultVariable;
import org.eclipse.persistence.jpa.jpql.parser.SelectClause;
import org.eclipse.persistence.jpa.jpql.parser.SelectStatement;
import org.eclipse.persistence.jpa.jpql.parser.SimpleFromClause;
import org.eclipse.persistence.jpa.jpql.parser.SimpleSelectClause;
import org.eclipse.persistence.jpa.jpql.parser.SimpleSelectStatement;
import org.eclipse.persistence.jpa.jpql.parser.SizeExpression;
import org.eclipse.persistence.jpa.jpql.parser.SqrtExpression;
import org.eclipse.persistence.jpa.jpql.parser.StartWithClause;
import org.eclipse.persistence.jpa.jpql.parser.StateFieldPathExpression;
import org.eclipse.persistence.jpa.jpql.parser.StringLiteral;
import org.eclipse.persistence.jpa.jpql.parser.SubExpression;
import org.eclipse.persistence.jpa.jpql.parser.SubstringExpression;
import org.eclipse.persistence.jpa.jpql.parser.SubtractionExpression;
import org.eclipse.persistence.jpa.jpql.parser.SumFunction;
import org.eclipse.persistence.jpa.jpql.parser.TableExpression;
import org.eclipse.persistence.jpa.jpql.parser.TableVariableDeclaration;
import org.eclipse.persistence.jpa.jpql.parser.TreatExpression;
import org.eclipse.persistence.jpa.jpql.parser.TrimExpression;
import org.eclipse.persistence.jpa.jpql.parser.TypeExpression;
import org.eclipse.persistence.jpa.jpql.parser.UnionClause;
import org.eclipse.persistence.jpa.jpql.parser.UnknownExpression;
import org.eclipse.persistence.jpa.jpql.parser.UpdateClause;
import org.eclipse.persistence.jpa.jpql.parser.UpdateItem;
import org.eclipse.persistence.jpa.jpql.parser.UpdateStatement;
import org.eclipse.persistence.jpa.jpql.parser.UpperExpression;
import org.eclipse.persistence.jpa.jpql.parser.ValueExpression;
import org.eclipse.persistence.jpa.jpql.parser.WhenClause;
import org.eclipse.persistence.jpa.jpql.parser.WhereClause;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.querykeys.ForeignReferenceQueryKey;
import org.eclipse.persistence.mappings.querykeys.QueryKey;
import org.eclipse.persistence.queries.ReportQuery;

/**
 * This {@link org.eclipse.persistence.jpa.jpql.parser.ExpressionVisitor} visits an {@link org.eclipse.persistence.jpa.jpql.parser.Expression
 * JPQL Expression} and creates the corresponding {@link org.eclipse.persistence.expressions.Expression EclipseLink Expression}.
 *
 * @version 2.6
 * @since 2.3
 * @author Pascal Filion
 * @author John Bracken
 */
@SuppressWarnings("nls")
final class ExpressionBuilderVisitor implements EclipseLinkExpressionVisitor {

    /**
     * This visitor creates a list by retrieving either the single child or the children of the
     * {@link CollectionExpression}, which would be the child.
     */
    private ChildrenExpressionVisitor childrenExpressionVisitor;

    /**
     * Determines whether the target relationship is allowed to be <code>null</code>.
     */
    private boolean nullAllowed;

    /**
     * This {@link Comparator} compares two {@link Class} values and returned the appropriate numeric
     * type that takes precedence.
     */
    private Comparator<Class<?>> numericTypeComparator;

    /**
     * The context used to query information about the application metadata.
     */
    private final JPQLQueryContext queryContext;

    /**
     * The EclipseLink {@link Expression} that represents a visited parsed
     * {@link org.eclipse persistence.jpa.query.parser.Expression Expression}
     */
    private Expression queryExpression;

    /**
     * Keeps track of the type of an expression while traversing it.
     */
    private final Class<?>[] type;

    /**
     * The visitor responsible to create the {@link Expression Expressions} for the <b>WHEN</b> and
     * <b>THEN</b> expressions.
     */
    private WhenClauseExpressionVisitor whenClauseExpressionVisitor;

    /**
     * Creates a new <code>ExpressionBuilderVisitor</code>.
     *
     * @param queryContext The context used to query information about the application metadata and
     * cached information
     */
    ExpressionBuilderVisitor(JPQLQueryContext queryContext) {
        super();
        this.type = new Class<?>[1];
        this.queryContext = queryContext;
    }

    private void appendJoinVariables(org.eclipse.persistence.jpa.jpql.parser.Expression expression,
                                     ReportQuery subquery) {

        queryExpression = null;

        for (String variableName : collectOuterIdentificationVariables()) {
            Expression innerExpression = queryContext.getQueryExpression(variableName);
            Expression outerExpression = queryContext.getParent().getQueryExpressionImp(variableName);
            Expression equalExpression = innerExpression.equal(outerExpression);

            if (queryExpression == null) {
                queryExpression = equalExpression;
            }
            else {
                queryExpression = queryExpression.and(equalExpression);
            }
        }

        // Aggregate the WHERE clause with the joins expression
        if (queryExpression != null) {
            Expression whereClause = subquery.getSelectionCriteria();

            if (whereClause != null) {
                whereClause = whereClause.and(queryExpression);
            }
            else {
                whereClause = queryExpression;
            }

            subquery.setSelectionCriteria(whereClause);
        }
    }

    /**
     * Creates a new EclipseLink {@link Expression} by visiting the given JPQL
     * {@link org.eclipse.persistence.jpa.jpql.parser.Expression Expression}.
     *
     * @param expression The {@link org.eclipse.persistence.jpa.jpql.parser.Expression Expression} to
     * convert into an EclipseLink {@link Expression}
     * @param type The type of the expression
     * @return The EclipseLink {@link Expression} of the JPQL fragment
     */
    Expression buildExpression(org.eclipse.persistence.jpa.jpql.parser.Expression expression,
                               Class<?>[] type) {

        Class<?> oldType = this.type[0];
        Expression oldQueryExpression = queryExpression;

        try {
            this.type[0]         = null;
            this.queryExpression = null;

            expression.accept(this);

            type[0] = this.type[0];
            return queryExpression;
        }
        finally {
            this.type[0]         = oldType;
            this.queryExpression = oldQueryExpression;
        }
    }

    /**
     * Creates a new EclipseLink {@link Expression} by visiting the given JPQL {@link
     * CollectionValuedPathExpression} that is used in the <code><b>GROUP BY</b></code> clause.
     *
     * @param expression The {@link CollectionValuedPathExpression} to convert into an EclipseLink
     * {@link Expression}
     * @return The EclipseLink {@link Expression} representation of that path expression
     */
    Expression buildGroupByExpression(CollectionValuedPathExpression expression) {


        try {
            PathResolver resolver     = new PathResolver();
            resolver.length           = expression.pathSize() - 1;
            resolver.nullAllowed      = false;
            resolver.checkMappingType = false;

            expression.accept(resolver);

            return resolver.localExpression;
        }
        finally {
            this.type[0]         = null;
            this.queryExpression = null;
        }
    }

    /**
     * Creates a new EclipseLink {@link Expression} by visiting the given JPQL {@link
     * StateFieldPathExpression}. This method temporarily changes the null allowed flag if the state
     * field is a foreign reference mapping
     *
     * @param expression The {@link StateFieldPathExpression} to convert into an EclipseLink {@link
     * Expression}
     * @return The EclipseLink {@link Expression} representation of that path expression
     */
    Expression buildModifiedPathExpression(StateFieldPathExpression expression) {


        try {
            PathResolver resolver     = new PathResolver();
            resolver.length           = expression.pathSize();
            resolver.checkMappingType = true;

            expression.accept(resolver);

            return resolver.localExpression;
        }
        finally {
            this.type[0]         = null;
            this.queryExpression = null;
        }
    }

    /**
     * Creates a new {@link ReportQuery} by visiting the given {@link SimpleSelectStatement}.
     *
     * @param expression The {@link SimpleSelectStatement} to convert into a {@link ReportQuery}
     * @return A fully initialized {@link ReportQuery}
     */
    ReportQuery buildSubquery(SimpleSelectStatement expression) {

        // First create the subquery
        ReportQuery subquery = new ReportQuery();
        queryContext.newSubQueryContext(expression, subquery);

        try {
            // Visit the subquery to populate it
            ReportQueryVisitor visitor = new ReportQueryVisitor(queryContext, subquery);
            expression.accept(visitor);
            type[0] = visitor.type;

            // Add the joins between the subquery and the parent query
            appendJoinVariables(expression, subquery);

            return subquery;
        }
        finally {
            queryContext.disposeSubqueryContext();
        }
    }

    private List<org.eclipse.persistence.jpa.jpql.parser.Expression> children(org.eclipse.persistence.jpa.jpql.parser.Expression expression) {
        ChildrenExpressionVisitor visitor = childrenExpressionVisitor();
        try {
            expression.accept(visitor);
            return new LinkedList<>(visitor.expressions);
        }
        finally {
            visitor.expressions.clear();
        }
    }

    private ChildrenExpressionVisitor childrenExpressionVisitor() {
        if (childrenExpressionVisitor == null) {
            childrenExpressionVisitor = new ChildrenExpressionVisitor();
        }
        return childrenExpressionVisitor;
    }

    private Set<String> collectOuterIdentificationVariables() {

        // Retrieve the identification variables used in the current query
        Set<String> variableNames = new HashSet<>(queryContext.getUsedIdentificationVariables());

        // Now remove the local identification variables that are defined in JOIN expressions and
        // in collection member declarations
        for (Declaration declaration : queryContext.getDeclarations()) {
            variableNames.remove(declaration.getVariableName());
        }

        return variableNames;
    }

    @Override
    public void visit(AbsExpression expression) {

        // First create the expression from the encapsulated expression
        expression.getExpression().accept(this);

        // Now create the ABS expression
        queryExpression = ExpressionMath.abs(queryExpression);

        // Note: The type will be calculated when traversing the ABS's expression
    }

    @Override
    public void visit(AbstractSchemaName expression) {
        ClassDescriptor descriptor = queryContext.getDescriptor(expression.getText());
        type[0] = descriptor.getJavaClass();
        queryExpression = new ExpressionBuilder(type[0]);
    }

    @Override
    public void visit(AdditionExpression expression) {

        List<Class<?>> types = new ArrayList<>(2);

        // Create the left side of the addition expression
        expression.getLeftExpression().accept(this);
        Expression leftExpression = queryExpression;
        types.add(type[0]);

        // Create the right side of the addition expression
        expression.getRightExpression().accept(this);
        Expression rightExpression = queryExpression;
        types.add(type[0]);

        // Now create the addition expression
        queryExpression = ExpressionMath.add(leftExpression, rightExpression);

        // Set the expression type
        Collections.sort(types, NumericTypeComparator.instance());
        type[0] = types.get(0);
    }

    @Override
    public void visit(AllOrAnyExpression expression) {

        // First create the subquery
        ReportQuery subquery = buildSubquery((SimpleSelectStatement) expression.getExpression());

        // Now create the ALL|SOME|ANY expression
        String identifier = expression.getIdentifier();
        queryExpression = queryContext.getBaseExpression();

        if (identifier == AllOrAnyExpression.ALL) {
            queryExpression = queryExpression.all(subquery);
        }
        else if (identifier == AllOrAnyExpression.SOME) {
            queryExpression = queryExpression.some(subquery);
        }
        else if (identifier == AllOrAnyExpression.ANY) {
            queryExpression = queryExpression.any(subquery);
        }

        // Note: The type will be calculated when traversing the ABS's expression
    }

    @Override
    public void visit(AndExpression expression) {

        // Create the left side of the logical expression
        expression.getLeftExpression().accept(this);
        Expression leftExpression = queryExpression;

        // Create the right side of the logical expression
        expression.getRightExpression().accept(this);
        Expression rightExpression = queryExpression;

        // Now create the AND expression
        queryExpression = leftExpression.and(rightExpression);

        // Set the expression type
        type[0] = Boolean.class;
    }

    @Override
    public void visit(ArithmeticFactor expression) {

        // First create the Expression that is prepended with the unary sign
        expression.getExpression().accept(this);
        Expression arithmeticFactor = queryExpression;

        // Create an expression for the constant 0 (zero)
        queryExpression = new ConstantExpression(0, new ExpressionBuilder());

        // "- <something>" is really "0 - <something>"
        queryExpression = ExpressionMath.subtract(queryExpression, arithmeticFactor);

        // Note: The type will be calculated when traversing the sub-expression
    }

    @Override
    public void visit(AsOfClause expression) {
        expression.getExpression().accept(this);
    }

    @Override
    public void visit(AvgFunction expression) {

        // First create the expression from the encapsulated expression
        expression.getExpression().accept(this);

        // Mark the AVG expression distinct
        if (expression.hasDistinct()) {
            queryExpression = queryExpression.distinct();
        }

        // Now create the AVG expression
        queryExpression = queryExpression.average();

        // Set the expression type
        type[0] = Double.class;
    }

    @Override
    public void visit(BadExpression expression) {
        // Nothing to do
    }

    @Override
    public void visit(BetweenExpression expression) {

        // First create the Expression for the result expression
        expression.getExpression().accept(this);
        Expression resultExpression = queryExpression;

        // Create the expression for the lower bound expression
        expression.getLowerBoundExpression().accept(this);
        Expression lowerBoundExpression = queryExpression;

        // Create the expression for the upper bound expression
        expression.getUpperBoundExpression().accept(this);
        Expression upperBoundExpression = queryExpression;

        // Create the BETWEEN expression
        if (expression.hasNot()) {
            queryExpression = resultExpression.notBetween(lowerBoundExpression, upperBoundExpression);
        }
        else {
            queryExpression = resultExpression.between(lowerBoundExpression, upperBoundExpression);
        }

        // Set the expression type
        type[0] = Boolean.class;
    }

    @Override
    public void visit(CaseExpression expression) {

        Expression caseBaseExpression = queryExpression;

        Expression caseOperandExpression = null;
        // Create the case operand expression
        if (expression.hasCaseOperand()) {
            expression.getCaseOperand().accept(this);
            caseOperandExpression = queryExpression;
        }

        WhenClauseExpressionVisitor visitor = whenClauseExpressionVisitor();

        try {
            // Create the WHEN clauses
            expression.getWhenClauses().accept(visitor);

            // Create the ELSE clause
            expression.getElseExpression().accept(this);
            Expression elseExpression = queryExpression;
            visitor.types.add(type[0]);

            // Create the CASE expression
            if (caseOperandExpression != null) {
                queryExpression = caseOperandExpression.caseStatement(visitor.whenClauses, elseExpression);

                //Bug 537795
                //After we build the caseStatement, we need to retroactively fix the THEN/ELSE children's base
                if(queryExpression.isFunctionExpression()) {
                    Vector<Expression> children = ((org.eclipse.persistence.internal.expressions.FunctionExpression)queryExpression).getChildren();
                    int index = 1;
                    while(index <  children.size()) {
                        Expression when_else = children.get(index);
                        if(index+1 < children.size()) {
                            //Not at end, must be a THEN
                            children.get(index+1).setLocalBase(caseBaseExpression);
                        } else {
                            //At end, must be an ELSE
                            when_else.setLocalBase(caseBaseExpression);
                        }
                        index=index+2;
                    }
                }
            }
            else {
                queryExpression = queryContext.getBaseExpression();
                queryExpression = queryExpression.caseStatement(visitor.whenClauses, elseExpression);
            }

            // Set the expression type
            type[0] = queryContext.typeResolver().compareCollectionEquivalentTypes(visitor.types);
        }
        finally {
            visitor.dispose();
        }
    }

    @Override
    public void visit(CastExpression expression) {

        // First create the expression from the encapsulated expression
        expression.getExpression().accept(this);

        // Now create the CAST expression
        org.eclipse.persistence.jpa.jpql.parser.Expression databaseType = expression.getDatabaseType();
        queryExpression = queryExpression.cast(databaseType.toParsedText());

        // Set the expression type
        type[0] = Object.class;
    }

    @Override
    public void visit(CoalesceExpression expression) {

        List<Expression> expressions = new ArrayList<>();
        List<Class<?>> types = new LinkedList<>();

        //cache the type of the expression so untyped children have a default type
        Class<?> coalesceType = type[0];

        // Create the Expression for each scalar expression
        for (org.eclipse.persistence.jpa.jpql.parser.Expression child : expression.getExpression().children()) {
            child.accept(this);
            expressions.add(queryExpression);

            //get the expression type parsed from the child expression
            Class<?> childType = type[0];

            // Default the type on an untyped ParameterExpression to the cached expression type.
            // This is to help provide a valid type for null parameter when binding JDBC parameter types
            if (queryExpression.isParameterExpression()) {
                ParameterExpression paramExpression = (ParameterExpression) queryExpression;
                if (paramExpression.getType() == null || paramExpression.getType().equals(Object.class)) {
                    paramExpression.setType(coalesceType);
                    childType = coalesceType;
                }
            }

            types.add(childType);
        }

        // Create the COALESCE expression
        queryExpression = queryContext.getBaseExpression();
        queryExpression = queryExpression.coalesce(expressions);

        // Set the expression type
        type[0] = queryContext.typeResolver().compareCollectionEquivalentTypes(types);
    }

    @Override
    public void visit(CollectionExpression expression) {
        // Nothing to do, this should be handled by the owning expression
    }

    @Override
    public void visit(CollectionMemberDeclaration expression) {
        expression.getCollectionValuedPathExpression().accept(this);
    }

    @Override
    public void visit(CollectionMemberExpression expression) {

        // Create the expression for the entity expression
        expression.getEntityExpression().accept(this);
        Expression entityExpression = queryExpression;

        if (expression.hasNot()) {

            CollectionValuedPathExpression pathExpression = (CollectionValuedPathExpression) expression.getCollectionValuedPathExpression();

            // Retrieve the ExpressionBuilder from the collection-valued path expression's
            // identification variable and the variable name
            pathExpression.getIdentificationVariable().accept(this);
            Expression parentExpression = queryExpression;

            // Now create the actual expression
            Expression newBuilder = new ExpressionBuilder();
            Expression collectionBase = newBuilder;
            for (int i = 1; i < pathExpression.pathSize() - 1; i++) {
                // nested paths must be single valued.
                collectionBase = collectionBase.get(pathExpression.getPath(i));
            }
            String lastPath = pathExpression.getPath(pathExpression.pathSize() - 1);
            // The following code is copied from Expression.noneOf and altered a bit
            Expression criteria = newBuilder.equal(parentExpression).and(collectionBase.anyOf(lastPath).equal(entityExpression));
            ReportQuery subQuery = new ReportQuery();
            subQuery.setShouldRetrieveFirstPrimaryKey(true);
            subQuery.setSelectionCriteria(criteria);
            // subQuery has the same reference class as parentExpression (which is an ExpressionBuilder).
            subQuery.setReferenceClass(((ExpressionBuilder)parentExpression).getQueryClass());
            queryExpression = parentExpression.notExists(subQuery);
        }
        else {
            // Create the expression for the collection-valued path expression
            expression.getCollectionValuedPathExpression().accept(this);

            // Create the MEMBER OF expression
            queryExpression = queryExpression.equal(entityExpression);
        }
    }

    @Override
    public void visit(CollectionValuedPathExpression expression) {
        visitPathExpression(expression, nullAllowed, expression.pathSize());
    }

    @Override
    public void visit(ComparisonExpression expression) {

        ComparisonExpressionVisitor visitor = new ComparisonExpressionVisitor();

        // Create the left side of the comparison expression
        expression.getLeftExpression().accept(visitor);
        Expression leftExpression = queryExpression;

        // Create the right side of the comparison expression
        expression.getRightExpression().accept(visitor);
        Expression rightExpression = queryExpression;

        // Now create the comparison expression
        String comparaison = expression.getComparisonOperator();

        // =
        if (comparaison == ComparisonExpression.EQUAL) {
            queryExpression = leftExpression.equal(rightExpression);
        }
        // <>, !=
        else if (comparaison == ComparisonExpression.DIFFERENT ||
                 comparaison == ComparisonExpression.NOT_EQUAL) {

            queryExpression = leftExpression.notEqual(rightExpression);
        }
        // <
        else if (comparaison == ComparisonExpression.LOWER_THAN) {
            queryExpression = leftExpression.lessThan(rightExpression);
        }
        // <=
        else if (comparaison == ComparisonExpression.LOWER_THAN_OR_EQUAL) {
            queryExpression = leftExpression.lessThanEqual(rightExpression);
        }
        // >
        else if (comparaison == ComparisonExpression.GREATER_THAN) {
            queryExpression = leftExpression.greaterThan(rightExpression);
        }
        // <=
        else if (comparaison == ComparisonExpression.GREATER_THAN_OR_EQUAL) {
            queryExpression = leftExpression.greaterThanEqual(rightExpression);
        }
        else {
            throw new IllegalArgumentException("The comparison operator is unknown: " + comparaison);
        }

        // Set the expression type
        type[0] = Boolean.class;
    }

    @Override
    public void visit(ConcatExpression expression) {

        List<org.eclipse.persistence.jpa.jpql.parser.Expression> expressions = children(expression.getExpression());
        Expression newExpression = null;

        for (org.eclipse.persistence.jpa.jpql.parser.Expression child : expressions) {
            child.accept(this);
            if (newExpression == null) {
                newExpression = queryExpression;
            }
            else {
                newExpression = newExpression.concat(queryExpression);
            }
        }

        queryExpression = newExpression;

        // Set the expression type
       type[0] = String.class;
    }

    @Override
    public void visit(ConnectByClause expression) {
        expression.getExpression().accept(this);
    }

    @Override
    public void visit(ConstructorExpression expression) {
        // Nothing to do
    }

    @Override
    public void visit(CountFunction expression) {

        // Create the expression from the encapsulated expression
        expression.getExpression().accept(this);

        // Mark the expression has distinct
        if (expression.hasDistinct()) {
            queryExpression = queryExpression.distinct();
        }

        // Create the COUNT expression
        queryExpression = queryExpression.count();

        // Set the expression type
        type[0] = Long.class;
    }

    @Override
    public void visit(DatabaseType expression) {
        // Nothing to do
    }

    @Override
    public void visit(DateTime expression) {

        if (expression.isJDBCDate()) {
            queryExpression = queryContext.getBaseExpression();
            queryExpression = new DateConstantExpression(expression.getText(), queryExpression);
            String text = expression.getText();

            if (text.startsWith("{d")) {
                type[0] = Date.class;
            }
            else if (text.startsWith("{ts")) {
                type[0] = Timestamp.class;
            }
            else if (text.startsWith("{t")) {
                type[0] = Time.class;
            }
            else {
                type[0] = Object.class;
            }
        }
        else {
            queryExpression = queryContext.getBaseExpression();

            if (expression.isCurrentDate()) {
                queryExpression = queryExpression.currentDateDate();
                type[0] = Date.class;
            }
            else if (expression.isCurrentTime()) {
                queryExpression = queryExpression.currentTime();
                type[0] = Time.class;
            }
            else if (expression.isCurrentTimestamp()) {
                queryExpression = queryExpression.currentTimeStamp();
                type[0] = Timestamp.class;
            }
            else {
                throw new IllegalArgumentException("The DateTime is unknown: " + expression);
            }
        }
    }

    @Override
    public void visit(DeleteClause expression) {
        // Nothing to do
    }

    @Override
    public void visit(DeleteStatement expression) {
        // Nothing to do
    }

    @Override
    public void visit(DivisionExpression expression) {

        List<Class<?>> types = new ArrayList<>(2);

        // Create the left side of the division expression
        expression.getLeftExpression().accept(this);
        Expression leftExpression = queryExpression;
        types.add(type[0]);

        // Create the right side of the division expression
        expression.getRightExpression().accept(this);
        Expression rightExpression = queryExpression;
        types.add(type[0]);

        // Now create the division expression
        queryExpression = ExpressionMath.divide(leftExpression, rightExpression);

        // Set the expression type
        Collections.sort(types, NumericTypeComparator.instance());
        type[0] = types.get(0);
    }

    @Override
    public void visit(EmptyCollectionComparisonExpression expression) {

        CollectionValuedPathExpression collectionPath = (CollectionValuedPathExpression) expression.getExpression();
        int lastPathIndex = collectionPath.pathSize() - 1;
        String name = collectionPath.getPath(lastPathIndex);

        // Create the expression for the collection-valued path expression (except the last path)
        visitPathExpression(collectionPath, false, lastPathIndex);

        // Create the IS EMPTY expression
        if (expression.hasNot()) {
            queryExpression = queryExpression.notEmpty(name);
        }
        else {
            queryExpression = queryExpression.isEmpty(name);
        }

        // Set the expression type
        type[0] = Boolean.class;
    }

    @Override
    public void visit(EntityTypeLiteral expression) {
        ClassDescriptor descriptor = queryContext.getDescriptor(expression.getEntityTypeName());
        type[0] = descriptor.getJavaClass();
        queryExpression = new ConstantExpression(type[0], queryContext.getBaseExpression());
    }

    @Override
    public void visit(EntryExpression expression) {

        // Create the expression for the collection-valued path expression
        expression.getExpression().accept(this);

        // Now create the ENTRY expression
        MapEntryExpression entryExpression = new MapEntryExpression(queryExpression);
        entryExpression.returnMapEntry();
        queryExpression = entryExpression;

        // Set the expression type
        type[0] = Map.Entry.class;
    }

    @Override
    public void visit(ExistsExpression expression) {

        // First create the subquery
        ReportQuery subquery = buildSubquery((SimpleSelectStatement) expression.getExpression());

        // Replace the SELECT clause of the exists subquery by SELECT 1 to avoid problems with
        // databases not supporting multiple columns in the subquery SELECT clause in SQL. The
        // original select clause expressions might include relationship navigations which should
        // result in FK joins in the generated SQL, e.g. ... EXISTS (SELECT o.customer FROM Order
        // o ...). Add the select clause expressions as non fetch join attributes to the ReportQuery
        // representing the subquery. This make sure the FK joins get generated
        for (ReportItem item : subquery.getItems()) {
            Expression expr = item.getAttributeExpression();
            subquery.addNonFetchJoinedAttribute(expr);
        }

        subquery.clearItems();

        Expression one = new ConstantExpression(1, new ExpressionBuilder());
        subquery.addItem("one", one);
        subquery.dontUseDistinct();

        // Now create the EXISTS expression
        queryExpression = queryContext.getBaseExpression();

        if (expression.hasNot()) {
            queryExpression = queryExpression.notExists(subquery);
        }
        else {
            queryExpression = queryExpression.exists(subquery);
        }

        // Set the expression type
        type[0] = Boolean.class;
    }

    @Override
    public void visit(ExtractExpression expression) {

        // First create the expression from the encapsulated expression
        expression.getExpression().accept(this);

        // Now create the EXTRACT expression
        queryExpression = queryExpression.extract(expression.getDatePart());

        // Set the expression type
        type[0] = Object.class;
    }

    @Override
    public void visit(FromClause expression) {
        // Nothing to do
    }

    @Override
    public void visit(FunctionExpression expression) {

        String identifier   = expression.getIdentifier();
        String functionName = expression.getUnquotedFunctionName();

        // COLUMN
        if (identifier == org.eclipse.persistence.jpa.jpql.parser.Expression.COLUMN) {

            // Create the expression for the single child
            expression.getExpression().accept(this);

            // Create the expression representing a field in a data-level query
            queryExpression = queryExpression.getField(functionName);
        }
        else {

            List<org.eclipse.persistence.jpa.jpql.parser.Expression> expressions = children(expression.getExpression());

            // No arguments
            if (expressions.isEmpty()) {
                queryExpression = queryContext.getBaseExpression();

                // OPERATOR
                if (identifier == org.eclipse.persistence.jpa.jpql.parser.Expression.SQL) {
                    queryExpression = queryExpression.literal(functionName);
                }
                // FUNC/FUNCTION
                else {
                    queryExpression = queryExpression.getFunction(functionName);
                }
            }
            // One or more arguments
            else {

                // Create the Expressions for the rest
                List<Expression> queryExpressions = new ArrayList<>(expressions.size());

                for (org.eclipse.persistence.jpa.jpql.parser.Expression child : expressions) {
                    child.accept(this);
                    queryExpressions.add(queryExpression);
                }

                queryExpression = queryExpressions.remove(0);

                // SQL
                if (identifier == org.eclipse.persistence.jpa.jpql.parser.Expression.SQL) {
                    queryExpression = queryExpression.sql(functionName, queryExpressions);
                }
                // OPERATOR
                else if (identifier == org.eclipse.persistence.jpa.jpql.parser.Expression.OPERATOR) {
                    queryExpression = queryExpression.operator(functionName, queryExpressions);
                }
                // FUNC/FUNCTION
                else {
                    queryExpression = queryExpression.getFunctionWithArguments(functionName, queryExpressions);
                }
            }
        }

        // Set the expression type
        type[0] = Object.class;
    }

    @Override
    public void visit(GroupByClause expression) {
        // Nothing to do
    }

    @Override
    public void visit(HavingClause expression) {
        expression.getConditionalExpression().accept(this);
    }

    @Override
    public void visit(HierarchicalQueryClause expression) {
        // Nothing to do
    }

    @Override
    public void visit(IdentificationVariable expression) {

        // The identification variable is virtual, only do something
        // if it falsely represents a state field path expression
        if (expression.isVirtual()) {
            StateFieldPathExpression stateFieldPathExpression = expression.getStateFieldPathExpression();

            if (stateFieldPathExpression != null) {
                stateFieldPathExpression.accept(this);
                return;
            }
        }

        String variableName = expression.getVariableName();

        // Identification variable, it's important to use findQueryExpression() and not
        // getQueryExpression(). If the identification variable is defined by the parent
        // query, then the ExpressionBuilder have most likely been created already
        queryExpression = queryContext.findQueryExpression(variableName);

        // Retrieve the Declaration mapped to the variable name
        Declaration declaration = queryContext.findDeclaration(variableName);

        // A null Declaration would most likely mean it's coming from a
        // state field path expression that represents an enum constant
        if (declaration != null) {

            // The Expression was not created yet, which can happen if the identification
            // variable is declared in a parent query. If that is the case, create the
            // ExpressionBuilder and cache it for the current query
            if (queryExpression == null) {
                declaration.getBaseExpression().accept(this);
                queryContext.addQueryExpression(variableName, queryExpression);
            }

            // Retrieve the Entity type
            if (declaration.getType() == Type.RANGE) {
                type[0] = declaration.getDescriptor().getJavaClass();
            }
        }
    }

    @Override
    public void visit(IdentificationVariableDeclaration expression) {
        // Nothing to do
    }

    @Override
    public void visit(IndexExpression expression) {

        // Create the expression for the encapsulated expression
        expression.getExpression().accept(this);

        // Now create the INDEX expression
        queryExpression = queryExpression.index();

        // Set the expression type
        type[0] = Integer.class;
    }

    @Override
    public void visit(InExpression expression) {

        // Visit the left expression
        InExpressionExpressionBuilder visitor1 = new InExpressionExpressionBuilder();
        expression.getExpression().accept(visitor1);

        // Visit the IN items
        InExpressionBuilder visitor2 = new InExpressionBuilder();
        visitor2.hasNot               = expression.hasNot();
        visitor2.singleInputParameter = expression.isSingleInputParameter();
        visitor2.leftExpression       = queryExpression;
        expression.getInItems().accept(visitor2);

        // Set the expression type
        type[0] = Boolean.class;
    }

    @Override
    public void visit(InputParameter expression) {

        String parameterName = expression.getParameter();

        // Calculate the input parameter type
        type[0] = queryContext.getParameterType(expression);

        // Create the expression
        queryExpression = queryContext.getBaseExpression();
        queryExpression = queryExpression.getParameter(parameterName.substring(1), type[0]);

        // Cache the input parameter type
        queryContext.addInputParameter(expression, queryExpression);
    }

    @Override
    public void visit(Join expression) {
        try {
            nullAllowed = expression.isLeftJoin();
            expression.getJoinAssociationPath().accept(this);
        }
        finally {
            nullAllowed = false;
        }
    }

    @Override
    public void visit(JPQLExpression expression) {
        // Nothing to do
    }

    @Override
    public void visit(KeyExpression expression) {

        // First visit the parent Expression
        expression.getExpression().accept(this);

        // Now create the Expression of the KEY expression
        queryExpression = new MapEntryExpression(queryExpression);
    }

    @Override
    public void visit(KeywordExpression expression) {

        String keyword = expression.getText();
        Object value;

        if (keyword == KeywordExpression.NULL) {
            value   = null;
            type[0] = Object.class;
        }
        else if (keyword == KeywordExpression.TRUE) {
            value   = Boolean.TRUE;
            type[0] = Boolean.class;
        }
        else {
            value   = Boolean.FALSE;
            type[0] = Boolean.class;
        }

        queryExpression = queryContext.getBaseExpression();
        queryExpression = new ConstantExpression(value, queryExpression);
    }

    @Override
    public void visit(LengthExpression expression) {

        // Create the expression from the encapsulated expression
        expression.getExpression().accept(this);

        // Now create the LENGTH expression
        queryExpression = queryExpression.length();

        // Set the expression type
        type[0] = Integer.class;
    }

    @Override
    public void visit(LikeExpression expression) {

        // Create the first expression
        expression.getStringExpression().accept(this);
        Expression firstExpression = queryExpression;

        // Create the expression for the pattern value
        expression.getPatternValue().accept(this);
        Expression patternValue = queryExpression;

        // Create the LIKE expression with the escape character
        if (expression.hasEscapeCharacter()) {
            expression.getEscapeCharacter().accept(this);
            queryExpression = firstExpression.like(patternValue, queryExpression);
        }
        // Create the LIKE expression with no escape character
        else {
            queryExpression = firstExpression.like(patternValue);
        }

        // Negate the expression
        if (expression.hasNot()) {
            queryExpression = queryExpression.not();
        }

        // Set the expression type
        type[0] = Boolean.class;
    }

    @Override
    public void visit(LocateExpression expression) {

        // Create the string to find in the find in expression
        expression.getFirstExpression().accept(this);
        Expression findExpression = queryExpression;

        // Create the find in string expression
        expression.getSecondExpression().accept(this);
        Expression findInExpression = queryExpression;

        // Create the expression for the start position
        expression.getThirdExpression().accept(this);
        Expression startPositionExpression = queryExpression;

        // Create the LOCATE expression
        if (startPositionExpression != null) {
            queryExpression = findInExpression.locate(findExpression, startPositionExpression);
        }
        else {
            queryExpression = findInExpression.locate(findExpression);
        }

        // Set the expression type
        type[0] = Integer.class;
    }

    @Override
    public void visit(LowerExpression expression) {

        // Create the expression from the encapsulated expression
        expression.getExpression().accept(this);

        // Now create the LOWER expression
        queryExpression = queryExpression.toLowerCase();

        // Set the expression type
        type[0] = String.class;
    }

    @Override
    public void visit(MaxFunction expression) {

        // Create the expression from the encapsulated expression
        expression.getExpression().accept(this);

        // Mark the MAX expression has distinct
        if (expression.hasDistinct()) {
            queryExpression = queryExpression.distinct();
        }

        // Now create the MAX expression
        queryExpression = queryExpression.maximum();

        // Note: The type will be calculated when traversing the sub-expression
    }

    @Override
    public void visit(MinFunction expression) {

        // Create the expression from the encapsulated expression
        expression.getExpression().accept(this);

        // Mark the MIN expression has distinct
        if (expression.hasDistinct()) {
            queryExpression = queryExpression.distinct();
        }

        // Now create the MIN expression
        queryExpression = queryExpression.minimum();

        // Note: The type will be calculated when traversing the sub-expression
    }

    @Override
    public void visit(ModExpression expression) {

        // First create the Expression for the first expression
        expression.getFirstExpression().accept(this);
        Expression leftExpression = queryExpression;

        // Now create the Expression for the second expression
        expression.getSecondExpression().accept(this);
        Expression rightExpression = queryExpression;

        // Now create the MOD expression
        queryExpression = ExpressionMath.mod(leftExpression, rightExpression);

        // Set the expression type
        type[0] = Integer.class;
    }

    @Override
    public void visit(MultiplicationExpression expression) {

        List<Class<?>> types = new ArrayList<>(2);

        // Create the left side of the multiplication expression
        expression.getLeftExpression().accept(this);
        Expression leftExpression = queryExpression;
        types.add(type[0]);

        // Create the right side of the multiplication expression
        expression.getRightExpression().accept(this);
        Expression rightExpression = queryExpression;
        types.add(type[0]);

        // Now create the multiplication expression
        queryExpression = ExpressionMath.multiply(leftExpression, rightExpression);

        // Set the expression type
        Collections.sort(types, NumericTypeComparator.instance());
        type[0] = types.get(0);
    }

    @Override
    public void visit(NotExpression expression) {

        // Create the expression
        expression.getExpression().accept(this);

        // Negate the expression
        queryExpression = queryExpression.not();

        // Set the expression type
        type[0] = Boolean.class;
    }

    @Override
    public void visit(NullComparisonExpression expression) {

        // Create the expression first
        expression.getExpression().accept(this);

        // Mark it as NOT NULL
        if (expression.hasNot()) {
            queryExpression = queryExpression.notNull();
        }
        // Mark it as IS NULL
        else {
            queryExpression = queryExpression.isNull();
        }

        // Set the expression type
        type[0] = Boolean.class;
    }

    @Override
    public void visit(NullExpression expression) {
        queryExpression = null;
        type[0] = null;
    }

    @Override
    public void visit(NullIfExpression expression) {

        // Create the first expression
        expression.getFirstExpression().accept(this);
        Expression firstExpression = queryExpression;
        Class<?> actualType = type[0];

        // Create the second expression
        expression.getSecondExpression().accept(this);
        Expression secondExpression = queryExpression;

        // Now create the NULLIF expression
        queryExpression = firstExpression.nullIf(secondExpression);

        // Set the expression type
        type[0] = actualType;
    }

    @Override
    public void visit(NumericLiteral expression) {

        // Instantiate a Number object with the value
        type[0] = queryContext.getType(expression);

        // Special case for a long number, Long.parseLong() does not handle 'l|L'
        // but Double.parseDouble() and Float.parseFloat() do handle 'd|D' and 'f|F', respectively
        String text = expression.getText();

        if ((type[0] == Long.class) && (text.endsWith("L") || text.endsWith("l"))) {
            text = text.substring(0, text.length() - 1);
        }

        Number number = queryContext.newInstance(type[0], String.class, text);

        // Now create the numeric expression
        queryExpression = new ConstantExpression(number, queryContext.getBaseExpression());
    }

    @Override
    public void visit(ObjectExpression expression) {
        // Simply traverse the OBJECT's expression
        expression.getExpression().accept(this);
    }

    @Override
    public void visit(OnClause expression) {
        expression.getConditionalExpression().accept(this);
    }

    @Override
    public void visit(OrderByClause expression) {
        // Nothing to do
    }

    @Override
    public void visit(OrderByItem expression) {

        // Create the item
        expression.getExpression().accept(this);

        // Create the ordering item
        switch (expression.getOrdering()) {
            case ASC:  queryExpression = queryExpression.ascending();  break;
            case DESC: queryExpression = queryExpression.descending(); break;
        }

        // Create the null ordering item
        switch (expression.getNullOrdering()) {
            case NULLS_FIRST: queryExpression = queryExpression.nullsFirst(); break;
            case NULLS_LAST:  queryExpression = queryExpression.nullsLast();  break;
        }
    }

    @Override
    public void visit(OrderSiblingsByClause expression) {
        expression.getOrderByItems().accept(this);
    }

    @Override
    public void visit(OrExpression expression) {

        // Create the left side of the logical expression
        expression.getLeftExpression().accept(this);
        Expression leftExpression = queryExpression;

        // Create the right side of the logical expression
        expression.getRightExpression().accept(this);
        Expression rightExpression = queryExpression;

        // Now create the OR expression
        queryExpression = leftExpression.or(rightExpression);

        // Set the expression type
        type[0] = Boolean.class;
    }

    @Override
    public void visit(RangeVariableDeclaration expression) {

        IdentificationVariable variable = (IdentificationVariable) expression.getIdentificationVariable();
        Declaration declaration = queryContext.getDeclaration(variable.getVariableName());

        switch (declaration.getType()) {

            // If the Declaration is RangeDeclaration, then retrieve its Descriptor directly,
            // this will support two cases automatically, the "root" object is
            // 1) An abstract schema name (entity name) -> parsed as AbstractSchemaName
            // 2) A fully qualified class name -> parsed as a CollectionValuedPathExpression
            //    that cannot be visited
            case RANGE:
            case CLASS_NAME: {
                type[0] = declaration.getDescriptor().getJavaClass();
                queryExpression = new ExpressionBuilder(type[0]);
                break;
            }

            // The FROM subquery needs to be created differently than a regular subquery
            case SUBQUERY: {
                type[0] = null;
                queryExpression = declaration.getQueryExpression();
                break;
            }

            // This should be a derived path (CollectionValuedPathExpression) or a subquery
            default: {
                expression.getRootObject().accept(this);
                break;
            }
        }
    }

    @Override
    public void visit(RegexpExpression expression) {

        // Create the first expression
        expression.getStringExpression().accept(this);
        Expression firstExpression = queryExpression;

        // Create the expression for the pattern value
        expression.getPatternValue().accept(this);
        Expression patternValue = queryExpression;

        // Create the REGEXP expression
        queryExpression = firstExpression.regexp(patternValue);

        // Set the expression type
        type[0] = Boolean.class;
    }

    @Override
    public void visit(ResultVariable expression) {

        expression.getSelectExpression().accept(this);
        IdentificationVariable identificationVariable = (IdentificationVariable) expression.getResultVariable();
        String variableName = identificationVariable.getVariableName();
        queryContext.addQueryExpression(variableName, queryExpression);

        // Note: The type will be calculated when traversing the select expression
    }

    @Override
    public void visit(SelectClause expression) {
        // Nothing to do
    }

    @Override
    public void visit(SelectStatement expression) {
        // Nothing to do
    }

    @Override
    public void visit(SimpleFromClause expression) {
        // Nothing to do
    }

    @Override
    public void visit(SimpleSelectClause expression) {
        // Nothing to do
    }

    @Override
    public void visit(SimpleSelectStatement expression) {

        // First create the subquery
        ReportQuery subquery = buildSubquery(expression);

        // Now wrap the subquery
        queryExpression = queryContext.getBaseExpression();
        queryExpression = queryExpression.subQuery(subquery);
    }

    @Override
    public void visit(SizeExpression expression) {

        CollectionValuedPathExpression pathExpression = (CollectionValuedPathExpression) expression.getExpression();
        int lastIndex = pathExpression.pathSize() - 1;

        // Create the right chain of expressions
        visitPathExpression(pathExpression, false, lastIndex - 1);

        // Now create the SIZE expression
        String name = pathExpression.getPath(lastIndex);
        queryExpression = queryExpression.size(name);

        // Set the expression type
        type[0] = Integer.class;
    }

    @Override
    public void visit(SqrtExpression expression) {

        // First create the expression from the encapsulated expression
        expression.getExpression().accept(this);

        // Now create the SQRT expression
        queryExpression = ExpressionMath.sqrt(queryExpression);

        // Set the expression type
        type[0] = Double.class;
    }

    @Override
    public void visit(StartWithClause expression) {
        expression.getConditionalExpression().accept(this);
    }

    @Override
    public void visit(StateFieldPathExpression expression) {
        visitPathExpression(expression, false, expression.pathSize());
    }

    @Override
    public void visit(StringLiteral expression) {

        // Create the expression
        queryExpression = queryContext.getBaseExpression();
        queryExpression = new ConstantExpression(expression.getUnquotedText(), queryExpression);

        // Set the expression type
        type[0] = String.class;
    }

    @Override
    public void visit(SubExpression expression) {
        expression.getExpression().accept(this);
    }

    @Override
    public void visit(SubstringExpression expression) {

        // Create the first expression
        expression.getFirstExpression().accept(this);
        Expression firstExpression = queryExpression;

        // Create the second expression
        expression.getSecondExpression().accept(this);
        Expression secondExpression = queryExpression;

        // Create the third expression
        expression.getThirdExpression().accept(this);
        Expression thirdExpression = queryExpression;

        // Now create the SUBSTRING expression
        if (thirdExpression != null) {
            queryExpression = firstExpression.substring(secondExpression, thirdExpression);
        }
        else {
            queryExpression = firstExpression.substring(secondExpression);
        }

        // Set the expression type
        type[0] = String.class;
    }

    @Override
    public void visit(SubtractionExpression expression) {

        List<Class<?>> types = new ArrayList<>(2);

        // Create the left side of the subtraction expression
        expression.getLeftExpression().accept(this);
        Expression leftExpression = queryExpression;
        types.add(type[0]);

        // Create the right side of the subtraction expression
        expression.getRightExpression().accept(this);
        Expression rightExpression = queryExpression;
        types.add(type[0]);

        // Now create the subtraction expression
        queryExpression = ExpressionMath.subtract(leftExpression, rightExpression);

        // Set the expression type
        Collections.sort(types, NumericTypeComparator.instance());
        type[0] = types.get(0);
    }

    @Override
    public void visit(SumFunction expression) {

        // First create the expression from the encapsulated expression
        expression.getExpression().accept(this);

        // Mark the SUM expression distinct
        if (expression.hasDistinct()) {
            queryExpression = queryExpression.distinct();
        }

        // Now create the SUM expression
        queryExpression = queryExpression.sum();

        // Set the expression type
        type[0] = queryContext.typeResolver().convertSumFunctionType(type[0]);
    }

    @Override
    public void visit(TableExpression expression) {
        String tableName = queryContext.literal(expression.getExpression(), LiteralType.STRING_LITERAL);
        tableName = ExpressionTools.unquote(tableName);
        queryExpression = queryContext.getBaseExpression().getTable(tableName);
    }

    @Override
    public void visit(TableVariableDeclaration expression) {
        // Nothing to do
    }

    @Override
    public void visit(TreatExpression expression) {

        // First visit the parent Expression
        expression.getCollectionValuedPathExpression().accept(this);

        // Now downcast the Expression
        EntityTypeLiteral entityTypeLiteral = (EntityTypeLiteral) expression.getEntityType();
        ClassDescriptor entityType = queryContext.getDescriptor(entityTypeLiteral.getEntityTypeName());
        queryExpression = queryExpression.treat(entityType.getJavaClass());
    }

    @Override
    public void visit(TrimExpression expression) {

        // Create the TRIM character expression
        expression.getTrimCharacter().accept(this);
        Expression trimCharacter = queryExpression;

        // Create the string to trim
        expression.getExpression().accept(this);
        Expression stringExpression = queryExpression;

        switch (expression.getSpecification()) {
            case LEADING: {
                if (trimCharacter != null) {
                    queryExpression = stringExpression.leftTrim(trimCharacter);
                }
                else {
                    queryExpression = stringExpression.leftTrim();
                }
                break;
            }
            case TRAILING: {
                if (trimCharacter != null) {
                    queryExpression = stringExpression.rightTrim(trimCharacter);
                }
                else {
                    queryExpression = stringExpression.rightTrim();
                }
                break;
            }
            default: {
                if (trimCharacter != null) {
                    queryExpression = stringExpression.trim(trimCharacter);
                }
                else {
                    queryExpression = stringExpression.trim();
                }
                break;
            }
        }

        // Set the expression type
        type[0] = String.class;
    }

    @Override
    public void visit(TypeExpression expression) {

        // First create the Expression for the identification variable
        expression.getExpression().accept(this);

        // Create the TYPE expression
        queryExpression = queryExpression.type();

        // Note: The type will be calculated when traversing the select expression
    }

    @Override
    public void visit(UnionClause expression) {
        // Nothing to do
    }

    @Override
    public void visit(UnknownExpression expression) {
        queryExpression = null;
    }

    @Override
    public void visit(UpdateClause expression) {
        // Nothing to do
    }

    @Override
    public void visit(UpdateItem expression) {
        // Nothing to do
    }

    @Override
    public void visit(UpdateStatement expression) {
        // Nothing to do
    }

    @Override
    public void visit(UpperExpression expression) {

        // First create the expression from the encapsulated expression
        expression.getExpression().accept(this);

        // Now create the UPPER expression
        queryExpression = queryExpression.toUpperCase();

        // Set the expression type
        type[0] = String.class;
    }

    @Override
    public void visit(ValueExpression expression) {
        expression.getExpression().accept(this);
    }

    @Override
    public void visit(WhenClause expression) {
        // Nothing to do
    }

    @Override
    public void visit(WhereClause expression) {
        expression.getConditionalExpression().accept(this);
    }

    private void visitPathExpression(AbstractPathExpression expression,
                                     boolean nullAllowed,
                                     int lastIndex) {


        PathResolver resolver = new PathResolver();

        resolver.length           = lastIndex;
        resolver.nullAllowed      = nullAllowed;
        resolver.checkMappingType = false;
        resolver.localExpression  = null;
        resolver.descriptor       = null;

        expression.accept(resolver);

        queryExpression = resolver.localExpression;
    }

    private WhenClauseExpressionVisitor whenClauseExpressionVisitor() {
        if (whenClauseExpressionVisitor == null) {
            whenClauseExpressionVisitor = new WhenClauseExpressionVisitor();
        }
        return whenClauseExpressionVisitor;
    }

    // Made static for performance reasons.
    /**
     * This visitor creates a list by retrieving either the single child or the children of the
     * {@link CollectionExpression}, which would be the child.
     */
    private static class ChildrenExpressionVisitor extends AnonymousExpressionVisitor {

        /**
         * The list of {@link org.eclipse.persistence.jpa.jpql.parser.Expression Expression} that are
         * the children of an expression.
         */
        List<org.eclipse.persistence.jpa.jpql.parser.Expression> expressions;

        /**
         * Creates a new <code>ChildrenExpressionVisitor</code>.
         */
        ChildrenExpressionVisitor() {
            super();
            expressions = new ArrayList<>();
        }

        @Override
        public void visit(CollectionExpression expression) {
            for (org.eclipse.persistence.jpa.jpql.parser.Expression child : expression.children()) {
                expressions.add(child);
            }
        }

        @Override
        public void visit(NullExpression expression) {
            // Can't be added to the list
        }

        @Override
        protected void visit(org.eclipse.persistence.jpa.jpql.parser.Expression expression) {
            expressions.add(expression);
        }
    }

    /**
     * This visitor makes sure to properly handle an entity type literal being parsed as an
     * identification variable.
     */
    private class ComparisonExpressionVisitor extends EclipseLinkAnonymousExpressionVisitor {

        @Override
        public void visit(IdentificationVariable expression) {

            boolean found = false;

            if (!expression.isVirtual()) {

                ClassDescriptor descriptor = queryContext.getDescriptor(expression.getText());

                // Entity type name
                if (descriptor != null) {
                    type[0] = descriptor.getJavaClass();
                    queryExpression = new ConstantExpression(type[0], queryContext.getBaseExpression());
                    found = true;
                }
            }

            if (!found) {
                expression.accept(ExpressionBuilderVisitor.this);
            }
        }

        @Override
        protected void visit(org.eclipse.persistence.jpa.jpql.parser.Expression expression) {
            expression.accept(ExpressionBuilderVisitor.this);
        }
    }

    /**
     * This visitor takes care of creating the left expression of an <code><b>IN</b></code> expression
     * and make sure to support nested arrays.
     */
    private class InExpressionExpressionBuilder extends EclipseLinkAnonymousExpressionVisitor {

        @Override
        public void visit(CollectionExpression expression) {

            // Assume this is a nested array
            List<Expression> children = new LinkedList<>();

            for (org.eclipse.persistence.jpa.jpql.parser.Expression child : expression.children()) {
                child.accept(this);
                children.add(queryExpression);
            }

            queryExpression = new org.eclipse.persistence.internal.expressions.CollectionExpression(children, queryContext.getBaseExpression());
        }

        @Override
        public void visit(org.eclipse.persistence.jpa.jpql.parser.Expression expression) {
            expression.accept(ExpressionBuilderVisitor.this);
        }

        @Override
        public void visit(SubExpression expression) {
            expression.getExpression().accept(this);
        }
    }

    /**
     * This visitor takes care of creating the <code><b>IN</b></code> expression by visiting the items.
     */
    private class InExpressionBuilder extends EclipseLinkAnonymousExpressionVisitor {

        private boolean hasNot;
        private Expression leftExpression;
        private boolean singleInputParameter;

        /**
         * Creates a new <code>InExpressionBuilder</code>.
         */
        InExpressionBuilder() {
            super();
        }

        @Override
        public void visit(CollectionExpression expression) {

            Collection<Expression> expressions = new ArrayList<>();
            InItemExpressionVisitor visitor = new InItemExpressionVisitor();

            for (org.eclipse.persistence.jpa.jpql.parser.Expression child : expression.children()) {
                child.accept(visitor);
                expressions.add(queryExpression);
            }

            if (hasNot) {
                queryExpression = leftExpression.notIn(expressions);
            }
            else {
                queryExpression = leftExpression.in(expressions);
            }
        }

        @Override
        public void visit(IdentificationVariable expression) {

            boolean found = false;

            if (!expression.isVirtual()) {

                ClassDescriptor descriptor = queryContext.getDescriptor(expression.getText());

                // Entity type name
                if (descriptor != null) {
                    type[0] = descriptor.getJavaClass();
                    queryExpression = new ConstantExpression(type[0], queryContext.getBaseExpression());
                    found = true;
                }
            }

            if (!found) {
                expression.accept(ExpressionBuilderVisitor.this);
            }
        }

        @Override
        public void visit(InputParameter expression) {

            if (singleInputParameter) {
                String parameterName = expression.getParameter();

                // Create the expression with Collection as the default type
                queryExpression = queryContext.getBaseExpression();
                queryExpression = queryExpression.getParameter(parameterName.substring(1), Collection.class);

                // Cache the input parameter type, which is by default Collection
                queryContext.addInputParameter(expression, queryExpression);

                if (hasNot) {
                    queryExpression = leftExpression.notIn(queryExpression);
                }
                else {
                    queryExpression = leftExpression.in(queryExpression);
                }
            }
            else {
                visit((org.eclipse.persistence.jpa.jpql.parser.Expression) expression);
            }
        }

        @Override
        protected void visit(org.eclipse.persistence.jpa.jpql.parser.Expression expression) {

            expression.accept(ExpressionBuilderVisitor.this);

            Collection<Expression> expressions = new ArrayList<>();
            expressions.add(queryExpression);

            // Now create the IN expression
            if (hasNot) {
                queryExpression = leftExpression.notIn(expressions);
            }
            else {
                queryExpression = leftExpression.in(expressions);
            }
        }

        @Override
        public void visit(SimpleSelectStatement expression) {

            // First create the subquery
            ReportQuery subquery = buildSubquery(expression);

            // Now create the IN expression
            if (hasNot) {
                queryExpression = leftExpression.notIn(subquery);
            }
            else {
                queryExpression = leftExpression.in(subquery);
            }
        }

        private class InItemExpressionVisitor extends AnonymousExpressionVisitor {


            @Override
            public void visit(IdentificationVariable expression) {
                ClassDescriptor descriptor = queryContext.getDescriptor(expression.getVariableName());
                queryExpression = queryContext.getBaseExpression();
                queryExpression = new ConstantExpression(descriptor.getJavaClass(), queryExpression);
            }


            @Override
            public void visit(CollectionExpression expression) {

                // Assume this is a nested array
                List<Expression> children = new LinkedList<>();

                for (org.eclipse.persistence.jpa.jpql.parser.Expression child : expression.children()) {
                    child.accept(this);
                    children.add(queryExpression);
                }

                queryExpression = new org.eclipse.persistence.internal.expressions.CollectionExpression(children, queryContext.getBaseExpression());
            }


            @Override
            public void visit(SubExpression expression) {
                expression.getExpression().accept(this);
            }


            @Override
            protected void visit(org.eclipse.persistence.jpa.jpql.parser.Expression expression) {
                expression.accept(ExpressionBuilderVisitor.this);
            }
        }
    }

    private class PathResolver extends AbstractEclipseLinkExpressionVisitor {

        /**
         * Determines whether
         */
        boolean checkMappingType;

        /**
         * Keeps track of the {@link Declaration} when the identification variable maps to a "root"
         * object defined in the <code><b>FROM</b></code> clause.
         */
        private Declaration declaration;

        /**
         * Keeps track of the descriptor while traversing the path expression.
         */
        private ClassDescriptor descriptor;

        /**
         * The actual number of paths within the path expression that will be traversed in order to
         * create the EclipseLink {@link Expression}.
         */
        int length;

        /**
         * The EclipseLink {@link Expression} that was retrieved or created while traversing the path
         * expression.
         */
        Expression localExpression;

        /**
         * Determines whether the target relationship is allowed to be <code>null</code>.
         */
        boolean nullAllowed;

        /**
         * Resolves a database column.
         *
         * @param expression The path expression representing an identification variable mapping to a
         * database table followed by the column name
         */
        private void resolveColumn(AbstractPathExpression expression) {
            String path = expression.getPath(1);
            localExpression = localExpression.getField(path);
        }

        /**
         * Attempts to resolve the path expression as a fully qualified enum constant.
         *
         * @param expression The {@link AbstractPathExpression} that might represent an enum constant
         * @return <code>true</code> if the path was a fully qualified enum constant; <code>false</code>
         * if it's an actual path expression
         */
        protected boolean resolveEnumConstant(AbstractPathExpression expression) {

            String fullPath = expression.toParsedText();
            Class<?> enumType = queryContext.getEnumType(fullPath);

            if (enumType != null) {

                // Make sure we keep track of the enum type
                type[0] = enumType;

                // Retrieve the enum constant
                String path = expression.getPath(expression.pathSize() - 1);
                Enum<?> enumConstant = retrieveEnumConstant(enumType, path);

                // Create the Expression
                localExpression = new ConstantExpression(enumConstant, new ExpressionBuilder());

                return true;
            }

            return false;
        }

        private void resolvePath(AbstractPathExpression expression) {

            for (int index = expression.hasVirtualIdentificationVariable() ? 0 : 1, count = length; index < count; index++) {

                String path = expression.getPath(index);
                DatabaseMapping mapping = descriptor.getObjectBuilder().getMappingForAttributeName(path);
                boolean last = (index + 1 == count);
                boolean collectionMapping = false;

                // The path is a mapping
                if (mapping != null) {

                    // Make sure we keep track of its type
                    if (type != null) {
                        type[0] = queryContext.calculateMappingType(mapping);
                    }

                    // This will tell us how to create the Expression
                    collectionMapping = mapping.isCollectionMapping();

                    // Retrieve the reference descriptor so we can continue traversing the path
                    if (!last) {
                        descriptor = mapping.getReferenceDescriptor();
                    }
                    // Flag that needs to be modified for a special case
                    else if (checkMappingType) {
                        nullAllowed = mapping.isForeignReferenceMapping();
                    }
                }
                // No mapping is defined for the single path, check for a query key
                else {
                    QueryKey queryKey = descriptor.getQueryKeyNamed(path);

                    if (queryKey != null) {
                        // Make sure we keep track of its type
                        if (type != null) {
                            type[0] = queryContext.calculateQueryKeyType(queryKey);
                        }

                        // This will tell us how to create the Expression
                        collectionMapping = queryKey.isCollectionQueryKey();

                        // Retrieve the reference descriptor so we can continue traversing the path
                        if (!last && queryKey.isForeignReferenceQueryKey()) {
                            ForeignReferenceQueryKey referenceQueryKey = (ForeignReferenceQueryKey) queryKey;
                            descriptor = queryContext.getDescriptor(referenceQueryKey.getReferenceClass());
                        }
                    }
                    // Nothing was found
                    else {
                        break;
                    }
                }

                // Now create the Expression
                if (collectionMapping) {
                    if (last && nullAllowed) {
                        localExpression = localExpression.anyOfAllowingNone(path);
                    }
                    else {
                        localExpression = localExpression.anyOf(path);
                    }
                }
                else {
                    if (last && nullAllowed) {
                        localExpression = localExpression.getAllowingNull(path);
                    }
                    else {
                        localExpression = localExpression.get(path);
                    }
                }
            }
        }

        private void resolveVirtualPath(AbstractPathExpression expression) {
            String path = expression.getPath(1);
            localExpression = localExpression.get(path);
        }

        /**
         * Retrieves the actual {@link Enum} constant with the given name.
         *
         * @param type The {@link Enum} class used to retrieve the given name
         * @param name The name of the constant to retrieve
         * @return The {@link Enum} constant
         */
        private Enum<?> retrieveEnumConstant(Class<?> type, String name) {

            for (Enum<?> enumConstant : (Enum<?>[]) type.getEnumConstants()) {
                if (name.equals(enumConstant.name())) {
                    return enumConstant;
                }
            }

            return null;
        }

        @Override
        public void visit(CollectionValuedPathExpression expression) {
            visitPathExpression(expression);
        }

        @Override
        public void visit(EntryExpression expression) {

            IdentificationVariable identificationVariable = (IdentificationVariable) expression.getExpression();
            String variableName = identificationVariable.getVariableName();

            // Retrieve the Expression for the identification variable
            declaration = queryContext.findDeclaration(variableName);
            declaration.getBaseExpression().accept(ExpressionBuilderVisitor.this);
            localExpression = queryExpression;

            // Create the Map.Entry expression
            MapEntryExpression entryExpression = new MapEntryExpression(localExpression);
            entryExpression.returnMapEntry();
            localExpression = entryExpression;
        }

        @Override
        public void visit(IdentificationVariable expression) {

            expression.accept(ExpressionBuilderVisitor.this);
            localExpression = queryExpression;

            // It is possible the Expression is null, it happens when the path expression is an enum
            // constant. If so, then no need to retrieve the descriptor
            if (localExpression != null) {
                declaration = queryContext.findDeclaration(expression.getVariableName());
                descriptor = declaration.getDescriptor();
            }
        }

        @Override
        public void visit(KeyExpression expression) {

            IdentificationVariable identificationVariable = (IdentificationVariable) expression.getExpression();

            // Create the Expression for the identification variable
            identificationVariable.accept(ExpressionBuilderVisitor.this);
            localExpression = new MapEntryExpression(queryExpression);

            // Retrieve the mapping's key mapping's descriptor
            descriptor = queryContext.resolveDescriptor(expression);
        }

        @Override
        public void visit(StateFieldPathExpression expression) {
            visitPathExpression(expression);
        }

        @Override
        public void visit(TreatExpression expression) {

            expression.accept(ExpressionBuilderVisitor.this);
            localExpression = queryExpression;

            // Retrieve the mapping's key mapping's descriptor
            descriptor = queryContext.resolveDescriptor(expression);
        }

        @Override
        public void visit(ValueExpression expression) {

            IdentificationVariable identificationVariable = (IdentificationVariable) expression.getExpression();

            // Create the Expression for the identification variable
            identificationVariable.accept(ExpressionBuilderVisitor.this);
            localExpression = queryExpression;

            // Retrieve the mapping's reference descriptor
            declaration = queryContext.findDeclaration(identificationVariable.getVariableName());
            descriptor = declaration.getDescriptor();
        }

        private void visitPathExpression(AbstractPathExpression expression) {

            // First resolve the identification variable
            expression.getIdentificationVariable().accept(this);

            // The path expression is composed with an identification
            // variable that is mapped to a subquery as the "root" object
            if ((declaration != null) && (declaration.getType() == Type.SUBQUERY)) {
                resolveVirtualPath(expression);
                return;
            }

            // A null value would most likely mean it's coming from a
            // state field path expression that represents an enum constant
            if (localExpression == null) {
                boolean result = resolveEnumConstant(expression);
                if (result) {
                    return;
                }
            }

            // The path expression is mapping to a database table
            if ((declaration != null) && (declaration.getType() == Type.TABLE)) {
                resolveColumn(expression);
                return;
            }

            // Traverse the rest of the path expression
            resolvePath(expression);
        }
    }

    /**
     * This visitor is responsible to create the {@link Expression Expressions} for the <b>WHEN</b>
     * and <b>THEN</b> expressions.
     */
    private class WhenClauseExpressionVisitor extends AbstractExpressionVisitor {

        /**
         * Keeps tracks of the type of each <code><b>WHEN</b></code> clauses.
         */
        final List<Class<?>> types;

        /**
         * The map of <b>WHEN</b> expressions mapped to their associated <b>THEN</b> expression.
         */
        Map<Expression, Expression> whenClauses;

        /**
         * Creates a new <code>WhenClauseExpressionVisitor</code>.
         */
        WhenClauseExpressionVisitor() {
            super();
            types = new LinkedList<>();
            whenClauses = new LinkedHashMap<>();
        }

        /**
         * Disposes this visitor.
         */
        void dispose() {
            types.clear();
            whenClauses.clear();
        }

        @Override
        public void visit(CollectionExpression expression) {
            expression.acceptChildren(this);
        }

        @Override
        public void visit(WhenClause expression) {

            // Create the WHEN expression
            expression.getWhenExpression().accept(ExpressionBuilderVisitor.this);
            Expression whenExpression = queryExpression;

            // Create the THEN expression
            expression.getThenExpression().accept(ExpressionBuilderVisitor.this);
            Expression thenExpression = queryExpression;
            types.add(type[0]);

            whenClauses.put(whenExpression, thenExpression);
        }
    }
}
