/*
 * 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);
        }

        @SuppressWarnings({"unchecked"})
        Number number = queryContext.newInstance((Class<? extends Number>) 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);
        }
    }
}
