/*
 * Copyright (c) 2011, 2021 Oracle and/or its affiliates. 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
//
package org.eclipse.persistence.internal.jpa.jpql;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.internal.descriptors.InstanceVariableAttributeAccessor;
import org.eclipse.persistence.internal.descriptors.MethodAttributeAccessor;
import org.eclipse.persistence.internal.queries.ContainerPolicy;
import org.eclipse.persistence.internal.queries.MappedKeyMapContainerPolicy;
import org.eclipse.persistence.jpa.jpql.ExpressionTools;
import org.eclipse.persistence.jpa.jpql.parser.*;
import org.eclipse.persistence.mappings.AttributeAccessor;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.DirectMapMapping;
import org.eclipse.persistence.mappings.querykeys.DirectQueryKey;
import org.eclipse.persistence.mappings.querykeys.ForeignReferenceQueryKey;
import org.eclipse.persistence.mappings.querykeys.QueryKey;

/**
 * This visitor resolves the type of any given {@link Expression}.
 *
 * @version 2.6
 * @since 2.4
 * @author Pascal Filion
 */
@SuppressWarnings("nls")
final class TypeResolver implements EclipseLinkExpressionVisitor {

    /**
     * This visitor is responsible to retrieve the {@link CollectionExpression} if it is visited.
     */
    private CollectionExpressionVisitor collectionExpressionVisitor;

    /**
     * This {@link Comparator} compares numeric types and sorts them based on precedence.
     */
    private Comparator<Class<?>> numericTypeComparator;

    /**
     * This visitor resolves a path expression by retrieving the mapping and descriptor of the last segment.
     */
    private PathResolver pathResolver;

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

    /**
     * The well defined type, which does not have to be calculated.
     */
    private Class<?> type;

    /**
     * A constant representing an unresolvable type.
     */
    private static final Class<?> UNRESOLVABLE_TYPE = TypeResolver.class;

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

    /**
     * Returns the type of the given {@link DatabaseMapping}, which is the persistent field type.
     *
     * @param mapping The {@link DatabaseMapping} to retrieve its persistent field type
     * @return The persistent field type
     */
    @SuppressWarnings("null")
    Class<?> calculateMappingType(DatabaseMapping mapping) {

        // For aggregate mappings (@Embedded and @EmbeddedId), we need to use the descriptor
        // because its mappings have to be retrieve from this one and not from the descriptor
        // returned when querying it with a Java type
        if (mapping.isAggregateMapping()) {
            ClassDescriptor descriptor = mapping.getReferenceDescriptor();
            if (descriptor != null) {
                return descriptor.getJavaClass();
            }
        }

        // Relationship mapping
        if (mapping.isForeignReferenceMapping()) {
            ClassDescriptor descriptor = mapping.getReferenceDescriptor();
            if (descriptor != null) {
                return descriptor.getJavaClass();
            }
        }
        // Collection mapping
        else if (mapping.isCollectionMapping()) {
            return mapping.getContainerPolicy().getContainerClass();
        }

        // Property mapping
        AttributeAccessor accessor = mapping.getAttributeAccessor();

        // Attribute
        if (accessor.isInstanceVariableAttributeAccessor()) {
            InstanceVariableAttributeAccessor attributeAccessor = (InstanceVariableAttributeAccessor) accessor;
            Field field = attributeAccessor.getAttributeField();

            if (field == null) {
                try {
                    field = mapping.getDescriptor().getJavaClass().getDeclaredField(attributeAccessor.getAttributeName());
                }
                catch (Exception e) {}
            }

            return field.getType();
        }

        // Property
        if (accessor.isMethodAttributeAccessor()) {
            MethodAttributeAccessor methodAccessor = (MethodAttributeAccessor) accessor;
            Method method = methodAccessor.getGetMethod();

            if (method == null) {
                try {
                    method = mapping.getDescriptor().getJavaClass().getDeclaredMethod(methodAccessor.getGetMethodName());
                }
                catch (Exception e) {}
            }

            return method.getReturnType();
        }

        // Anything else
        return accessor.getAttributeClass();
    }

    /**
     * Returns the type of the given {@link QueryKey}, which is the persistent field type.
     *
     * @param queryKey The {@link QueryKey} to retrieve its persistent field type
     * @return The persistent field type
     */
    Class<?> calculateQueryKeyType(QueryKey queryKey) {

        // ForeignReferenceQueryKey
        if (queryKey.isForeignReferenceQueryKey()) {
            ForeignReferenceQueryKey foreignReferenceQueryKey = (ForeignReferenceQueryKey) queryKey;
            return foreignReferenceQueryKey.getReferenceClass();
        }

        // DirectQueryKey
        DirectQueryKey key = (DirectQueryKey) queryKey;
        Class<?> type = key.getField().getType();
        return (type != null) ? type : Object.class;
    }

    /**
     * Returns the visitor that collects the {@link CollectionExpression} if it's been visited.
     *
     * @return The {@link CollectionExpressionVisitor}
     */
    protected CollectionExpressionVisitor collectionExpressionVisitor() {
        if (collectionExpressionVisitor == null) {
            collectionExpressionVisitor = new CollectionExpressionVisitor();
        }
        return collectionExpressionVisitor;
    }

    Class<?> compareCollectionEquivalentTypes(List<Class<?>> types) {

        Class<?> localType = null;

        for (Class<?> anotherType : types) {

            if (anotherType == UNRESOLVABLE_TYPE) {
                continue;
            }

            if (localType == null) {
                localType = anotherType;
            }
            // Two types are not the same, then the type is Object
            else if (localType != anotherType) {
                return Object.class;
            }
        }

        if (localType == null) {
            localType = UNRESOLVABLE_TYPE;
        }

        return localType;
    }

    Class<?> convertSumFunctionType(Class<?> type) {

        // Integral types
        if ((type == Integer.TYPE)   ||
            (type == Integer.class)  ||
            (type == Long.TYPE)      ||
            (type == Long.class)     ||
            (type == Byte.TYPE)      ||
            (type == Byte.class)     ||
            (type == Short.TYPE)     ||
            (type == Short.class)    ||
            (type == Character.TYPE) ||
            (type == Character.class)) {

            type = Long.class;
        }

        // Floating types
        else if ((type == Float.TYPE)  ||
                 (type == Float.class) ||
                 (type == Double.TYPE) ||
                 (type == Double.class)) {

            type = Double.class;
        }

        // Anything else, use Object
        else if ((type != BigDecimal.class) &&
                 (type != BigInteger.class)) {

            type = Object.class;
        }

        return type;
    }

    /**
     * Casts the given {@link Expression} to a {@link CollectionExpression} if it is actually an
     * object of that type.
     *
     * @param expression The {@link Expression} to cast
     * @return The given {@link Expression} if it is a {@link CollectionExpression} or <code>null</code>
     * if it is any other object
     */
    private CollectionExpression getCollectionExpression(Expression expression) {
        CollectionExpressionVisitor visitor = collectionExpressionVisitor();
        try {
            expression.accept(visitor);
            return visitor.expression;
        }
        finally {
            visitor.expression = null;
        }
    }

    private boolean isNumericType() {
        return type == Integer.TYPE     || type == Integer.class ||
               type == Long.TYPE        || type == Long.class    ||
               type == Float.TYPE       || type == Float.class   ||
               type == Double.TYPE      || type == Double.class  ||
               type == BigInteger.class || type == BigDecimal.class;
    }

    private PathResolver pathResolver() {
        if (pathResolver == null) {
            pathResolver = new PathResolver();
        }
        return pathResolver;
    }

    /**
     * Returns the type of the given {@link Expression}.
     *
     * @param expression The {@link Expression} to resolve its type
     * @return Either the closest type or {@link Object} if it could not be determined
     */
    Class<?> resolve(Expression expression) {
        Class<?> oldType = type;
        try {
            expression.accept(this);
            return (type == UNRESOLVABLE_TYPE) ? Object.class : type;
        }
        finally {
            type = oldType;
        }
    }

    ClassDescriptor resolveDescriptor(Expression expression) {

        PathResolver resolver = pathResolver();

        DatabaseMapping oldMapping    = resolver.mapping;
        ClassDescriptor oldDescriptor = resolver.descriptor;

        try {
            resolver.mapping    = null;
            resolver.descriptor = null;

            expression.accept(resolver);

            return resolver.descriptor;
        }
        finally {
            resolver.mapping    = oldMapping;
            resolver.descriptor = oldDescriptor;
        }
    }

    DatabaseMapping resolveMapping(Expression expression) {

        PathResolver resolver = pathResolver();

        QueryKey oldQueryKey          = resolver.queryKey;
        DatabaseMapping oldMapping    = resolver.mapping;
        ClassDescriptor oldDescriptor = resolver.descriptor;

        try {
            resolver.mapping    = null;
            resolver.descriptor = null;
            resolver.queryKey   = null;

            expression.accept(resolver);

            return resolver.mapping;
        }
        finally {
            resolver.mapping    = oldMapping;
            resolver.queryKey   = oldQueryKey;
            resolver.descriptor = oldDescriptor;
        }
    }

    /**
     * Resolves the given {@link org.eclipse.persistence.jpa.jpql.parser.Expression Expression} and
     * either returns the {@link DatabaseMapping} or the {@link QueryKey} object.
     *
     * @param expression The {@link org.eclipse.persistence.jpa.jpql.parser.Expression Expression} to
     * resolve by traversing its path expression
     * @return Either the {@link DatabaseMapping} or the {@link QueryKey} that is representing the
     * last path or <code>null</code> if the path expression could not be resolved
     */
    Object resolveMappingObject(Expression expression) {

        PathResolver resolver = pathResolver();

        QueryKey oldQueryKey          = resolver.queryKey;
        DatabaseMapping oldMapping    = resolver.mapping;
        ClassDescriptor oldDescriptor = resolver.descriptor;

        try {
            resolver.mapping    = null;
            resolver.descriptor = null;
            resolver.queryKey   = null;

            expression.accept(resolver);
            return (resolver.mapping != null) ? resolver.mapping : resolver.queryKey;
        }
        finally {
            resolver.mapping    = oldMapping;
            resolver.queryKey   = oldQueryKey;
            resolver.descriptor = oldDescriptor;
        }
    }

    private Class<?> resolveMappingType(AbstractPathExpression expression) {

        PathResolver resolver = pathResolver();

        QueryKey oldQueryKey          = resolver.queryKey;
        DatabaseMapping oldMapping    = resolver.mapping;
        ClassDescriptor oldDescriptor = resolver.descriptor;

        try {
            resolver.mapping    = null;
            resolver.descriptor = null;
            resolver.queryKey   = null;

            expression.accept(resolver);

            if (resolver.mapping != null) {
                return calculateMappingType(resolver.mapping);
            }
            else if (resolver.queryKey != null) {
                return calculateQueryKeyType(resolver.queryKey);
            }
            else {
                return queryContext.getEnumType(expression.toParsedText());
            }
        }
        finally {
            resolver.mapping    = oldMapping;
            resolver.queryKey   = oldQueryKey;
            resolver.descriptor = oldDescriptor;
        }
    }

    QueryKey resolveQueryKey(org.eclipse.persistence.jpa.jpql.parser.Expression expression) {

        PathResolver resolver = pathResolver();

        QueryKey oldQueryKey          = resolver.queryKey;
        DatabaseMapping oldMapping    = resolver.mapping;
        ClassDescriptor oldDescriptor = resolver.descriptor;

        try {
            resolver.mapping    = null;
            resolver.descriptor = null;
            resolver.queryKey   = null;

            expression.accept(resolver);
            return resolver.queryKey;
        }
        finally {
            resolver.mapping    = oldMapping;
            resolver.queryKey   = oldQueryKey;
            resolver.descriptor = oldDescriptor;
        }
    }

    @Override
    public void visit(AbsExpression expression) {
        // Visit the child expression in order to create the resolver
        expression.getExpression().accept(this);
    }

    @Override
    public void visit(AbstractSchemaName expression) {
        ClassDescriptor descriptor = queryContext.getDescriptor(expression.getText());
        type = descriptor.getJavaClass();
    }

    @Override
    public void visit(AdditionExpression expression) {
        visitArithmeticExpression(expression);
    }

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

    @Override
    public void visit(AndExpression expression) {
        type = Boolean.class;
    }

    @Override
    public void visit(ArithmeticFactor expression) {

        // First traverse the expression
        expression.getExpression().accept(this);

        // Make sure the type is a numeric type
        if (!isNumericType()) {
            type = Object.class;
        }
    }

    @Override
    public void visit(AsOfClause expression) {
        type = Object.class;
    }

    @Override
    public void visit(AvgFunction expression) {
        type = Double.class;
    }

    @Override
    public void visit(BadExpression expression) {
        type = Object.class;
    }

    @Override
    public void visit(BetweenExpression expression) {
        type = Boolean.class;
    }

    @Override
    public void visit(CaseExpression expression) {
        visitCollectionEquivalentExpression(
            expression.getWhenClauses(),
            expression.getElseExpression()
        );
    }

    @Override
    public void visit(CastExpression expression) {
        type = Object.class;
    }

    @Override
    public void visit(CoalesceExpression expression) {
        visitCollectionEquivalentExpression(expression.getExpression(), null);
    }

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

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

    @Override
    public void visit(CollectionMemberExpression expression) {
        type = Boolean.class;
    }

    @Override
    public void visit(CollectionValuedPathExpression expression) {
        type = resolveMappingType(expression);
    }

    @Override
    public void visit(ComparisonExpression expression) {
        type = Boolean.class;
    }

    @Override
    public void visit(ConcatExpression expression) {
        type = String.class;
    }

    @Override
    public void visit(ConnectByClause expression) {
        type = Object.class;
    }

    @Override
    public void visit(ConstructorExpression expression) {
        type = queryContext.getType(expression.getClassName());
    }

    @Override
    public void visit(CountFunction expression) {
        type = Long.class;
    }

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

    @Override
    public void visit(DateTime expression) {

        if (expression.isCurrentDate()) {
            type = Date.class;
        }
        else if (expression.isCurrentTime()) {
            type = Time.class;
        }
        else if (expression.isCurrentTimestamp()) {
            type = Timestamp.class;
        }
        else {
            String text = expression.getText();

            if (text.startsWith("{d")) {
                type = Date.class;
            }
            else if (text.startsWith("{ts")) {
                type = Timestamp.class;
            }
            else if (text.startsWith("{t")) {
                type = Time.class;
            }
            else {
                type = Object.class;
            }
        }
    }

    @Override
    public void visit(DeleteClause expression) {
        type = Object.class;
    }

    @Override
    public void visit(DeleteStatement expression) {
        type = Object.class;
    }

    @Override
    public void visit(DivisionExpression expression) {
        visitArithmeticExpression(expression);
    }

    @Override
    public void visit(EmptyCollectionComparisonExpression expression) {
        type = Boolean.class;
    }

    @Override
    public void visit(EntityTypeLiteral expression) {
        String entityTypeName = expression.getEntityTypeName();
        ClassDescriptor descriptor = queryContext.getDescriptor(entityTypeName);
        type = descriptor.getJavaClass();
    }

    @Override
    public void visit(EntryExpression expression) {
        type = Map.Entry.class;
    }

    @Override
    public void visit(ExistsExpression expression) {
        type = Boolean.class;
    }

    @Override
    public void visit(ExtractExpression expression) {
        type = Object.class;
    }

    @Override
    public void visit(FromClause expression) {
        type = Object.class;
    }

    @Override
    public void visit(FunctionExpression expression) {
        type = Object.class;
    }

    @Override
    public void visit(GroupByClause expression) {
        type = Object.class;
    }

    @Override
    public void visit(HavingClause expression) {
        type = Object.class;
    }

    @Override
    public void visit(HierarchicalQueryClause expression) {
        type = Object.class;
    }

    @Override
    public void visit(IdentificationVariable expression) {

        PathResolver resolver = pathResolver();

        DatabaseMapping oldMapping    = resolver.mapping;
        ClassDescriptor oldDescriptor = resolver.descriptor;

        try {
            resolver.mapping    = null;
            resolver.descriptor = null;

            expression.accept(resolver);

            if (resolver.mapping != null) {
                type = calculateMappingType(resolver.mapping);
            }
            else if (resolver.descriptor != null) {
                type = resolver.descriptor.getJavaClass();
            }
            else {
                type = Object.class;
            }
        }
        finally {
            resolver.mapping    = oldMapping;
            resolver.descriptor = oldDescriptor;
        }
    }

    @Override
    public void visit(IdentificationVariableDeclaration expression) {
        type = Object.class;
    }

    @Override
    public void visit(IndexExpression expression) {
        type = Integer.class;
    }

    @Override
    public void visit(InExpression expression) {
        type = Boolean.class;
    }

    @Override
    public void visit(InputParameter expression) {
        type = UNRESOLVABLE_TYPE;
    }

    @Override
    public void visit(Join expression) {
        expression.getJoinAssociationPath().accept(this);
    }

    @Override
    public void visit(JPQLExpression expression) {
        expression.getQueryStatement().accept(this);
    }

    @Override
    public void visit(KeyExpression expression) {
        IdentificationVariable identificationVariable = (IdentificationVariable) expression.getExpression();
        Declaration declaration = queryContext.findDeclaration(identificationVariable.getVariableName());
        DatabaseMapping mapping = declaration.getMapping();
        MappedKeyMapContainerPolicy mapContainerPolicy = (MappedKeyMapContainerPolicy) mapping.getContainerPolicy();
        type = (Class<?>) mapContainerPolicy.getKeyType();
    }

    @Override
    public void visit(KeywordExpression expression) {

        String text = expression.getText();

        if (text == KeywordExpression.FALSE ||
            text == KeywordExpression.TRUE) {

            type = Boolean.class;
        }
        else {
            type = Object.class;
        }
    }

    @Override
    public void visit(LengthExpression expression) {
        type = Integer.class;
    }

    @Override
    public void visit(LikeExpression expression) {
        type = Boolean.class;
    }

    @Override
    public void visit(LocateExpression expression) {
        type = Integer.class;
    }

    @Override
    public void visit(LowerExpression expression) {
        type = String.class;
    }

    @Override
    public void visit(MaxFunction expression) {

        // Visit the state field path expression in order to create the resolver
        expression.getExpression().accept(this);

        // Wrap the Resolver used to determine the type of the state field
        // path expression so we can return the actual type
        if (!isNumericType()) {
            type = Object.class;
        }
    }

    @Override
    public void visit(MinFunction expression) {

        // Visit the state field path expression in order to create the resolver
        expression.getExpression().accept(this);

        // Wrap the Resolver used to determine the type of the state field
        // path expression so we can return the actual type
        if (!isNumericType()) {
            type = Object.class;
        }
    }

    @Override
    public void visit(ModExpression expression) {
        type = Integer.class;
    }

    @Override
    public void visit(MultiplicationExpression expression) {
        visitArithmeticExpression(expression);
    }

    @Override
    public void visit(NotExpression expression) {
        type = Boolean.class;
    }

    @Override
    public void visit(NullComparisonExpression expression) {
        type = Boolean.class;
    }

    @Override
    public void visit(NullExpression expression) {
        type = UNRESOLVABLE_TYPE;
    }

    @Override
    public void visit(NullIfExpression expression) {
        expression.getFirstExpression().accept(this);
    }

    @Override
    public void visit(NumericLiteral expression) {

        try {
            String text = expression.getText();

            // Long value
            // Integer value
            if (ExpressionTools.LONG_REGEXP   .matcher(text).matches() ||
                ExpressionTools.INTEGER_REGEXP.matcher(text).matches()) {

                // Special case for a long number, Long.parseLong() does not handle 'l|L'
                if (text.endsWith("L") || text.endsWith("l")) {
                    type = Long.class;
                }
                else {
                    Long value = Long.parseLong(text);

                    if (value <= Integer.MAX_VALUE) {
                        type = Integer.class;
                    }
                    else {
                        type = Long.class;
                    }
                }
            }
            // Float
            else if (ExpressionTools.FLOAT_REGEXP.matcher(text).matches()) {
                type = Float.class;
            }
            // Decimal
            else if (ExpressionTools.DOUBLE_REGEXP.matcher(text).matches()) {
                type = Double.class;
            }
        }
        catch (Exception e) {
            type = Object.class;
        }
    }

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

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

    @Override
    public void visit(OrderByClause expression) {
        type = Object.class;
    }

    @Override
    public void visit(OrderByItem expression) {
        type = Object.class;
    }

    @Override
    public void visit(OrderSiblingsByClause expression) {
        type = Object.class;
    }

    @Override
    public void visit(OrExpression expression) {
        type = Boolean.class;
    }

    @Override
    public void visit(RangeVariableDeclaration expression) {
        type = Object.class;
    }

    @Override
    public void visit(RegexpExpression expression) {
        type = Boolean.class;
    }

    @Override
    public void visit(ResultVariable expression) {
        expression.getSelectExpression().accept(this);
    }

    @Override
    public void visit(SelectClause expression) {

        Expression selectExpression = expression.getSelectExpression();

        // visit(CollectionExpression) iterates through the children but for a
        // SELECT clause, a CollectionExpression means the result type is Object[]
        CollectionExpression collectionExpression = getCollectionExpression(selectExpression);

        if (collectionExpression != null) {
            type = Object[].class;
        }
        else {
            selectExpression.accept(this);
        }
    }

    @Override
    public void visit(SelectStatement expression) {
        expression.getSelectClause().accept(this);
    }

    @Override
    public void visit(SimpleFromClause expression) {
        type = Object.class;
    }

    @Override
    public void visit(SimpleSelectClause expression) {
        expression.getSelectExpression().accept(this);
    }

    @Override
    public void visit(SimpleSelectStatement expression) {
        queryContext.newSubQueryContext(expression, null);
        try {
            expression.getSelectClause().accept(this);
        }
        finally {
            queryContext.disposeSubqueryContext();
        }
    }

    @Override
    public void visit(SizeExpression expression) {
        type = Integer.class;
    }

    @Override
    public void visit(SqrtExpression expression) {
        type = Double.class;
    }

    @Override
    public void visit(StartWithClause expression) {
        type = Object.class;
    }

    @Override
    public void visit(StateFieldPathExpression expression) {
        type = resolveMappingType(expression);
    }

    @Override
    public void visit(StringLiteral expression) {
        type = String.class;
    }

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

    @Override
    public void visit(SubstringExpression expression) {
        type = String.class;
    }

    @Override
    public void visit(SubtractionExpression expression) {
        visitArithmeticExpression(expression);
    }

    @Override
    public void visit(SumFunction expression) {

        // Visit the state field path expression in order to create the resolver
        expression.getExpression().accept(this);

        // Wrap the Resolver used to determine the type of the state field
        // path expression so we can return the actual type
        type = convertSumFunctionType(type);
    }

    @Override
    public void visit(TableExpression expression) {
        type = Object.class;
    }

    @Override
    public void visit(TableVariableDeclaration expression) {
        type = Object.class;
    }

    @Override
    public void visit(TreatExpression expression) {
        expression.getEntityType().accept(this);
    }

    @Override
    public void visit(TrimExpression expression) {
        type = String.class;
    }

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

    @Override
    public void visit(UnionClause expression) {
        type = Object.class;
    }

    @Override
    public void visit(UnknownExpression expression) {
        type = Object.class;
    }

    @Override
    public void visit(UpdateClause expression) {
        type = Object.class;
    }

    @Override
    public void visit(UpdateItem expression) {
        type = Object.class;
    }

    @Override
    public void visit(UpdateStatement expression) {
        type = Object.class;
    }

    @Override
    public void visit(UpperExpression expression) {
        type = String.class;
    }

    @Override
    public void visit(ValueExpression expression) {

        IdentificationVariable identificationVariable = (IdentificationVariable) expression.getExpression();
        Declaration declaration = queryContext.findDeclaration(identificationVariable.getVariableName());
        DatabaseMapping mapping = declaration.getMapping();

        if (mapping.isDirectMapMapping()) {

            DirectMapMapping mapMapping = (DirectMapMapping) mapping;
            type = mapMapping.getValueClass();

            if (type == null) {
                type = mapMapping.getDirectField().getType();
            }
        }
        else {
            type = calculateMappingType(declaration.getMapping());
        }
    }

    @Override
    public void visit(WhenClause expression) {
        expression.getThenExpression().accept(this);
    }

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

    /**
     * Visits the given {@link ArithmeticExpression} and creates the appropriate {@link org.eclipse.
     * persistence.expressions.Expression Expression}.
     *
     * @param expression The {@link ArithmeticExpression} to visit
     */
    private void visitArithmeticExpression(ArithmeticExpression expression) {

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

        // Visit the first expression
        expression.getLeftExpression().accept(this);
        if (isNumericType()) {
            types.add(type);
        }

        // Visit the second expression
        expression.getRightExpression().accept(this);
        if (isNumericType()) {
            types.add(type);
        }

        if (types.size() == 2) {
            Collections.sort(types, NumericTypeComparator.instance());
            type = types.get(0);
        }
        else {
            type = Object.class;
        }
    }

    /**
     * Visits the given {@link Expression} and creates the appropriate {@link org.eclipse.persistence.
     * expressions.Expression Expression} that will check the type for each of its children. If the
     * type is the same, then it's the {@link Expression}'s type; otherwise the type will be {@link Object}.
     *
     * @param expression The {@link Expression} to calculate the type of its children
     * @param extraExpression This {@link Expression} will be resolved, if it's not <code>null</code>
     * and its type will be added to the collection of types
     */
    private void visitCollectionEquivalentExpression(Expression expression,
                                                     Expression extraExpression) {

        List<Class<?>> types = new ArrayList<>();
        CollectionExpression collectionExpression = getCollectionExpression(expression);

        // Gather the resolver for all children
        if (collectionExpression != null) {
            for (Expression child : collectionExpression.children()) {
                child.accept(this);
                types.add(type);
            }
        }
        // Otherwise visit the actual expression
        else {
            expression.accept(this);
            types.add(type);
        }

        // Add the resolver for the other expression
        if (extraExpression != null) {
            extraExpression.accept(this);
            types.add(type);
        }

        // Now compare the types
        type = compareCollectionEquivalentTypes(types);
    }

    /**
     * This visitor is used to check if the expression visited is a {@link CollectionExpression}.
     */
    private static class CollectionExpressionVisitor extends AbstractExpressionVisitor {

        /**
         * The {@link CollectionExpression} that was visited, otherwise <code>null</code>.
         */
        protected CollectionExpression expression;

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

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

    private class PathResolver extends AbstractEclipseLinkExpressionVisitor {

        ClassDescriptor descriptor;
        DatabaseMapping mapping;
        QueryKey queryKey;

        @Override
        public void visit(AbstractSchemaName expression) {
            descriptor = queryContext.getDescriptor(expression.getText());
        }

        /**
         * {@link InputParameter}
         */
        @Override
        public void visit(CollectionValuedPathExpression expression) {
            visitPathExpression(expression);
        }

        @Override
        public void visit(EntityTypeLiteral expression) {
            descriptor = queryContext.getDescriptor(expression.getEntityTypeName());
        }

        /**
         * {@link InputParameter}
         */
        @Override
        public void visit(IdentificationVariable expression) {

            // Check to see if the identification variable is "virtual" and internally
            // changed to a state field path expression. If so, it means it's an unqualified
            // path found in an UPDATE or DELETE query
            StateFieldPathExpression pathExpression = expression.isVirtual() ? expression.getStateFieldPathExpression() : null;

            if (pathExpression != null) {
                pathExpression.accept(this);
            }
            else {
                Declaration declaration = queryContext.findDeclaration(expression.getVariableName());

                // A null declaration Expression would mean it's the first package of an enum type
                if (declaration != null) {
                    descriptor = declaration.getDescriptor();
                }
            }
        }

        /**
         * {@link InputParameter}
         */
        @Override
        public void visit(Join expression) {
            expression.getJoinAssociationPath().accept(this);
        }

        /**
         * {@link InputParameter}
         */
        @Override
        public void visit(KeyExpression expression) {

            IdentificationVariable identificationVariable = (IdentificationVariable) expression.getExpression();
            Declaration declaration = queryContext.getDeclaration(identificationVariable.getVariableName());
            DatabaseMapping mapping = declaration.getMapping();

            ContainerPolicy containerPolicy = mapping.getContainerPolicy();
            MappedKeyMapContainerPolicy mapPolicy = (MappedKeyMapContainerPolicy) containerPolicy;
            descriptor = mapPolicy.getKeyMapping().getReferenceDescriptor();
        }

        @Override
        public void visit(RangeVariableDeclaration expression) {
            expression.getIdentificationVariable().accept(this);
        }

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

        /**
         * {@link InputParameter}
         */
        @Override
        public void visit(TreatExpression expression) {
            expression.getEntityType().accept(this);
        }

        /**
         * {@link InputParameter}
         */
        @Override
        public void visit(ValueExpression expression) {
            IdentificationVariable identificationVariable = (IdentificationVariable) expression.getExpression();
            Declaration declaration = queryContext.getDeclaration(identificationVariable.getVariableName());
            descriptor = declaration.getDescriptor();
        }

        private void visitPathExpression(AbstractPathExpression expression) {

            expression.getIdentificationVariable().accept(this);

            if (descriptor == null) {
                return;
            }

            // Now traverse the rest of the path
            for (int index = expression.hasVirtualIdentificationVariable() ? 0 : 1, count = expression.pathSize(); index < count; index++) {

                String path = expression.getPath(index);
                mapping = descriptor.getObjectBuilder().getMappingForAttributeName(path);

                if (mapping == null) {
                    queryKey = descriptor.getQueryKeyNamed(path);

                    if ((queryKey != null) && queryKey.isForeignReferenceQueryKey()) {
                        ForeignReferenceQueryKey referenceQueryKey = (ForeignReferenceQueryKey) queryKey;
                        descriptor = queryContext.getDescriptor(referenceQueryKey.getReferenceClass());
                    }
                    else {
                        if (index + 1 < count) {
                            mapping = null;
                        }
                        descriptor = null;
                    }
                }
                // A collection mapping cannot be used in a path (if it's not the last path)
                else if (mapping.isCollectionMapping() && (index + 1 < count)) {
                    mapping    = null;
                    descriptor = null;
                }
                else {
                    descriptor = mapping.getReferenceDescriptor();
                }

                if (descriptor == null) {
                    if (index + 1 < count) {
                        mapping = null;
                    }
                    break;
                }
            }
        }
    }
}
