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