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

// Contributors:
//     Oracle - initial API and implementation
//
//     09/02/2019-3.0 - Alexandre Jacob
//       - 527415: Fix code when locale is tr, az or lt
package org.eclipse.persistence.jpa.jpql;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.eclipse.persistence.jpa.jpql.JPQLQueryDeclaration.Type;
import org.eclipse.persistence.jpa.jpql.parser.AbsExpression;
import org.eclipse.persistence.jpa.jpql.parser.AbstractExpressionVisitor;
import org.eclipse.persistence.jpa.jpql.parser.AbstractFromClause;
import org.eclipse.persistence.jpa.jpql.parser.AbstractSchemaName;
import org.eclipse.persistence.jpa.jpql.parser.AbstractSingleEncapsulatedExpression;
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.ArithmeticExpression;
import org.eclipse.persistence.jpa.jpql.parser.ArithmeticFactor;
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.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.CompoundExpression;
import org.eclipse.persistence.jpa.jpql.parser.ConcatExpression;
import org.eclipse.persistence.jpa.jpql.parser.ConstructorExpression;
import org.eclipse.persistence.jpa.jpql.parser.CountFunction;
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.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.Expression;
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.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.JPQLGrammar;
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.RangeVariableDeclaration;
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.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.TreatExpression;
import org.eclipse.persistence.jpa.jpql.parser.TrimExpression;
import org.eclipse.persistence.jpa.jpql.parser.TypeExpression;
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 static org.eclipse.persistence.jpa.jpql.JPQLQueryProblemMessages.*;

/**
 * The base validator responsible to gather the problems found in a JPQL query by validating the
 * content to make sure it is semantically valid, i.e. based on the information contained in the
 * JPA application. The grammar is not validated by this visitor.
 * <p>
 * Provisional API: This interface is part of an interim API that is still under development and
 * expected to change significantly before reaching stability. It is available at this early stage
 * to solicit feedback from pioneering adopters on the understanding that any code that uses this
 * API will almost certainly be broken (repeatedly) as the API evolves.
 *
 * @see AbstractGrammarValidator
 *
 * @version 2.5.1
 * @since 2.4
 * @author Pascal Filion
 */
@SuppressWarnings("nls")
public abstract class AbstractSemanticValidator extends AbstractValidator {

    /**
     * This visitor is responsible to retrieve the visited {@link Expression} if it is a
     * {@link CollectionValuedPathExpression}.
     */
    protected CollectionValuedPathExpressionVisitor collectionValuedPathExpressionVisitor;

    /**
     * This visitor is responsible to check if the entity type literal (parsed as an identification
     * variable) is part of a comparison expression.
     */
    private ComparingEntityTypeLiteralVisitor comparingEntityTypeLiteralVisitor;

    /**
     * This visitor visits the left and right expressions of a {@link ComparisonExpressionVisitor}
     * and gather information that is used by {@link #validateComparisonExpression(ComparisonExpression)}.
     */
    private ComparisonExpressionVisitor comparisonExpressionVisitor;

    /**
     * The given helper allows this validator to access the JPA artifacts without using Hermes SPI.
     */
    protected final SemanticValidatorHelper helper;

    /**
     * This visitor makes sure the path expressions are properly validated.
     */
    private InItemsVisitor inItemsVisitor;

    /**
     * This flag is used to register the {@link IdentificationVariable IdentificationVariables} that
     * are used throughout the query (top-level query and subqueries), except the identification
     * variables defining an abstract schema name or a collection-valued path expression.
     */
    protected boolean registerIdentificationVariable;

    /**
     * This visitor is responsible to retrieve the visited {@link Expression} if it is a
     * {@link StateFieldPathExpression}.
     */
    protected StateFieldPathExpressionVisitor stateFieldPathExpressionVisitor;

    /**
     *
     */
    private SubqueryFirstDeclarationVisitor subqueryFirstDeclarationVisitor;

    /**
     *
     */
    private TopLevelFirstDeclarationVisitor topLevelFirstDeclarationVisitor;

    /**
     * The {@link IdentificationVariable IdentificationVariables} that are used throughout the query
     * (top-level query and subqueries), except the identification variables defining an abstract
     * schema name or a collection-valued path expression.
     */
    protected List<IdentificationVariable> usedIdentificationVariables;

    /**
     * This finder is responsible to retrieve the virtual identification variable from the
     * <b>UPDATE</b> range declaration since it is optional.
     */
    protected BaseDeclarationIdentificationVariableFinder virtualIdentificationVariableFinder;

    /**
     * Creates a new <code>AbstractSemanticValidator</code>.
     *
     * @param helper The given helper allows this validator to access the JPA artifacts without using
     * Hermes SPI
     * @exception NullPointerException The given {@link SemanticValidatorHelper} cannot be <code>null</code>
     */
    protected AbstractSemanticValidator(SemanticValidatorHelper helper) {
        super();
        Assert.isNotNull(helper, "The helper cannot be null");
        this.helper = helper;
    }

    protected ComparingEntityTypeLiteralVisitor buildComparingEntityTypeLiteralVisitor() {
        return new ComparingEntityTypeLiteralVisitor();
    }

    protected InItemsVisitor buildInItemsVisitor() {
        return new InItemsVisitor(this);
    }

    protected SubqueryFirstDeclarationVisitor buildSubqueryFirstDeclarationVisitor() {
        return new SubqueryFirstDeclarationVisitor();
    }

    protected TopLevelFirstDeclarationVisitor buildTopLevelFirstDeclarationVisitor() {
        return new TopLevelFirstDeclarationVisitor();
    }

    @Override
    public void dispose() {
        super.dispose();
        usedIdentificationVariables.clear();
    }

    /**
     * Returns the {@link IdentificationVariable} that defines the identification variable for either
     * a <code><b>DELETE</b></code> or an <code><b>UPDATE</b></code> query.
     *
     * @param expression The {@link AbstractSchemaName} that is being validated and that most likely
     * representing an associated path expression and not an entity name
     * @return The {@link IdentificationVariable} defining either the identification variable or the
     * virtual identification variable for the <code><b>DELETE</b></code> or for the
     * <code><b>UPDATE</b></code> query
     */
    protected IdentificationVariable findVirtualIdentificationVariable(AbstractSchemaName expression) {
        BaseDeclarationIdentificationVariableFinder visitor = getVirtualIdentificationVariableFinder();
        try {
            expression.accept(visitor);
            return visitor.expression;
        }
        finally {
            visitor.expression = null;
        }
    }

    protected CollectionValuedPathExpression getCollectionValuedPathExpression(Expression expression) {
        CollectionValuedPathExpressionVisitor visitor = getCollectionValuedPathExpressionVisitor();
        try {
            expression.accept(visitor);
            return visitor.expression;
        }
        finally {
            visitor.expression = null;
        }
    }

    protected CollectionValuedPathExpressionVisitor getCollectionValuedPathExpressionVisitor() {
        if (collectionValuedPathExpressionVisitor == null) {
            collectionValuedPathExpressionVisitor = new CollectionValuedPathExpressionVisitor();
        }
        return collectionValuedPathExpressionVisitor;
    }

    protected ComparingEntityTypeLiteralVisitor getComparingEntityTypeLiteralVisitor() {
        if (comparingEntityTypeLiteralVisitor == null) {
            comparingEntityTypeLiteralVisitor = buildComparingEntityTypeLiteralVisitor();
        }
        return comparingEntityTypeLiteralVisitor;
    }

    protected ComparisonExpressionVisitor getComparisonExpressionVisitor() {
        if (comparisonExpressionVisitor == null) {
            comparisonExpressionVisitor = new ComparisonExpressionVisitor(this);
        }
        return comparisonExpressionVisitor;
    }

    @Override
    protected JPQLGrammar getGrammar() {
        return helper.getGrammar();
    }

    protected InItemsVisitor getInItemsVisitor() {
        if (inItemsVisitor == null) {
            inItemsVisitor = buildInItemsVisitor();
        }
        return inItemsVisitor;
    }

    protected StateFieldPathExpression getStateFieldPathExpression(Expression expression) {
        StateFieldPathExpressionVisitor visitor = getStateFieldPathExpressionVisitor();
        try {
            expression.accept(visitor);
            return visitor.expression;
        }
        finally {
            visitor.expression = null;
        }
    }

    protected StateFieldPathExpressionVisitor getStateFieldPathExpressionVisitor() {
        if (stateFieldPathExpressionVisitor == null) {
            stateFieldPathExpressionVisitor = new StateFieldPathExpressionVisitor();
        }
        return stateFieldPathExpressionVisitor;
    }

    /**
     * Returns the visitor that can find the {@link IdentificationVariable} of the {@link
     * RangeVariableDeclaration}. This should be used when the query is either a <code><b>DELETE</b></code>
     * or <code><b>UPDATE</b></code> query.
     *
     * @return The visitor that can traverse the query and returns the {@link IdentificationVariable}
     */
    protected BaseDeclarationIdentificationVariableFinder getVirtualIdentificationVariableFinder() {
        if (virtualIdentificationVariableFinder == null) {
            virtualIdentificationVariableFinder = new BaseDeclarationIdentificationVariableFinder();
        }
        return virtualIdentificationVariableFinder;
    }

    @Override
    protected void initialize() {
        super.initialize();
        usedIdentificationVariables    = new ArrayList<>();
        registerIdentificationVariable = true;
    }

    /**
     * Determines whether the given identification variable is used in a comparison expression:
     * "expression = LargeProject".
     *
     * @param expression The {@link IdentificationVariable} used to determine its purpose
     * @return <code>true</code> if the identification variable is used in a comparison expression;
     * <code>false</code> otherwise
     */
    protected boolean isComparingEntityTypeLiteral(IdentificationVariable expression) {
        ComparingEntityTypeLiteralVisitor visitor = getComparingEntityTypeLiteralVisitor();
        try {
            visitor.expression = expression;
            expression.accept(visitor);
            return visitor.result;
        }
        finally {
            visitor.result     = false;
            visitor.expression = null;
        }
    }

    protected boolean isIdentificationVariableDeclaredAfter(String variableName,
                                                            int variableNameIndex,
                                                            int joinIndex,
                                                            List<JPQLQueryDeclaration> declarations) {

        for (int index = variableNameIndex, declarationCount = declarations.size(); index < declarationCount; index++) {

            JPQLQueryDeclaration declaration = declarations.get(index);

            // Ignore the current declaration since it's the same identification variable
            if (index != variableNameIndex) {

                // Check to make sure the Declaration is a known type
                if (declaration.getType() != Type.UNKNOWN) {
                    String nextVariableName = declaration.getVariableName();

                    if (variableName.equalsIgnoreCase(nextVariableName)) {
                        return true;
                    }
                }
                // Some implementation could have a Declaration that is not a range, derived or a
                // collection Declaration, it could represent a JOIN expression
                else {
                    return false;
                }
            }

            // Scan the JOIN expressions
            if (declaration.hasJoins()) {

                List<Join> joins = declaration.getJoins();
                int endIndex = (index == variableNameIndex) ? joinIndex : joins.size();

                for (int subIndex = joinIndex; subIndex < endIndex; subIndex++) {

                    Join join = joins.get(subIndex);

                    String joinVariableName = literal(
                        join.getIdentificationVariable(),
                        LiteralType.IDENTIFICATION_VARIABLE
                    );

                    if (variableName.equalsIgnoreCase(joinVariableName)) {
                        return true;
                    }
                }
            }
        }

        // The identification variable was not found after the declaration being validated, that means
        // it was defined before or it was not defined (which is validated by another rule)
        return false;
    }

    /**
     * Determines whether an identification variable can be used in a comparison expression when the
     * operator is either {@literal '<', '<=', '>', '>='}.
     *
     * @param expression The {@link IdentificationVariable} that is mapped to either an entity, a
     * singled-object value field, a collection-valued object field
     * @return <code>true</code> if it can be used in a ordering comparison expression; <code>false</code>
     * if it can't
     */
    protected boolean isIdentificationVariableValidInComparison(IdentificationVariable expression) {
        return helper.isIdentificationVariableValidInComparison(expression);
    }

    /**
     * Determines whether the given {@link ComparisonExpression} compares two expression using one of
     * the following operators: {@literal '<', '<=', '>', '>='}.
     *
     * @param expression The {@link ComparisonExpression} to check what type of operator that is used
     * @return <code>true</code> if the operator is used to check for order; <code>false</code> if it
     * is not
     */
    protected boolean isOrderComparison(ComparisonExpression expression) {

        String operator = expression.getComparisonOperator();

        return operator == Expression.GREATER_THAN          ||
               operator == Expression.GREATER_THAN_OR_EQUAL ||
               operator == Expression.LOWER_THAN            ||
               operator == Expression.LOWER_THAN_OR_EQUAL;
    }

    /**
     * Determines whether the expression at the given index is valid or not.
     *
     * @param result The integer value containing the bit used to determine the state of an expression
     * at a given position
     * @param index The index that is used to determine the state of the expression
     * @return <code>true</code> if the expression is valid at the given index
     */
    protected final boolean isValid(int result, int index) {
        return (result & (1 << index)) == 0;
    }

    /**
     * Returns the type of path expression that is allowed in the <code><b>SELECT</b></code> clause.
     *
     * @return The type of path expressions allowed. The spec defines it as basic or object mapping
     * only, i.e. collection-valued path expression is not allowed
     */
    protected abstract PathType selectClausePathExpressionPathType();

    protected FirstDeclarationVisitor subqueryFirstDeclarationVisitor() {
        if (subqueryFirstDeclarationVisitor == null) {
            subqueryFirstDeclarationVisitor = buildSubqueryFirstDeclarationVisitor();
        }
        return subqueryFirstDeclarationVisitor;
    }

    protected FirstDeclarationVisitor topLevelFirstDeclarationVisitor() {
        if (topLevelFirstDeclarationVisitor == null) {
            topLevelFirstDeclarationVisitor = buildTopLevelFirstDeclarationVisitor();
        }
        return topLevelFirstDeclarationVisitor;
    }

    /**
     * Updates the validation status of an expression at a specified position. The value is stored
     * in an integer value.
     *
     * @param result The integer value that is used to store the validation status of an expression
     * at the given position
     * @param index The position to store the validation status
     * @param valid The new validation status to store
     * @return The updated integer value
     */
    protected final int updateStatus(int result, int index, boolean valid) {
        return valid ? (result & (0 << index)) : (result | (1 << index));
    }

    /**
     * Validates the encapsulated expression of the given <code><b>ABS</b></code> expression. The
     * test to perform is:
     * <ul>
     * <li>If the encapsulated expression is a path expression, validation makes sure it is a basic
     * mapping, an association field is not allowed.</li>
     * <li>If the encapsulated expression is not a path expression, validation will be redirected to
     * that expression but the returned status will not be changed.</li>
     * </ul>
     *
     * @param expression The {@link AbsExpression} to validate by validating its encapsulated
     * expression
     * @return <code>false</code> if the encapsulated expression was validated and is invalid;
     * <code>true</code> otherwise
     */
    protected boolean validateAbsExpression(AbsExpression expression) {
        return validateFunctionPathExpression(expression);
    }

    /**
     * Validates the given <code><b>FROM</b></code> clause. This will validate the order of
     * identification variable declarations.
     *
     * @param expression The {@link AbstractFromClause} to validate
     */
    protected void validateAbstractFromClause(AbstractFromClause expression,
                                              FirstDeclarationVisitor visitor) {

        // The identification variable declarations are evaluated from left to right in
        // the FROM clause, and an identification variable declaration can use the result
        // of a preceding identification variable declaration of the query string
        List<JPQLQueryDeclaration> declarations = helper.getDeclarations();

        for (int index = 0, count = declarations.size(); index < count; index++) {

            JPQLQueryDeclaration declaration = declarations.get(index);

            // Make sure the first declaration is valid
            if (index == 0) {
                validateFirstDeclaration(expression, declaration, visitor);
            }
            else {
                Expression declarationExpression = declaration.getDeclarationExpression();

                // A JOIN expression does not have a declaration and it should not be traversed here
                if (declarationExpression != null) {
                    declarationExpression.accept(this);
                }
            }

            // Check the JOIN expressions in the identification variable declaration
            if (declaration.hasJoins()) {
                validateJoinsIdentificationVariable(expression, declarations, declaration, index);
            }
            // Check the collection member declaration or derived path expression
            else {

                Type type = declaration.getType();

                if (type == Type.DERIVED ||
                    type == Type.COLLECTION) {

                    // Retrieve the identification variable from the path expression
                    String variableName = literal(
                        declaration.getBaseExpression(),
                        LiteralType.PATH_EXPRESSION_IDENTIFICATION_VARIABLE
                    );

                    if (ExpressionTools.stringIsNotEmpty(variableName) &&
                        isIdentificationVariableDeclaredAfter(variableName, index, -1, declarations)) {

                        int startPosition = position(declaration.getDeclarationExpression()) - variableName.length();
                        int endPosition   = startPosition + variableName.length();

                        addProblem(
                            expression,
                            startPosition,
                            endPosition,
                            AbstractFromClause_WrongOrderOfIdentificationVariableDeclaration,
                            variableName
                        );
                    }
                }
            }
        }
    }

    /**
     * Validates the given {@link AbstractSchemaName}. The tests to perform are:
     * <ul>
     *    <li>Check to see the actual entity associated with the entity name does exist.</li>
     *    <li>If the abstract schema name is actually a path expression (which can be defined in a
     *        subquery but is always parsed as an abstract schema name), then make sure the path
     *        expression is resolving to a relationship mapping.</li>
     * </ul>
     *
     * @param expression The {@link AbstractSchemaName} to validate
     * @return <code>true</code> if the entity name was resolved; <code>false</code> otherwise
     */
    protected boolean validateAbstractSchemaName(AbstractSchemaName expression) {

        String abstractSchemaName = expression.getText();
        Object managedType = helper.getEntityNamed(abstractSchemaName);
        boolean valid = true;

        if (managedType == null) {

            // If a subquery is defined in a WHERE clause of an update query,
            // then check for a path expression
            if (isWithinSubquery(expression)) {

                // Find the identification variable from the UPDATE range declaration
                IdentificationVariable identificationVariable = findVirtualIdentificationVariable(expression);
                String variableName = (identificationVariable != null) ? identificationVariable.getText() : null;

                if (ExpressionTools.stringIsNotEmpty(variableName)) {

                    Object mapping = helper.resolveMapping(variableName, abstractSchemaName);
                    Object type = helper.getMappingType(mapping);

                    // Does not resolve to a valid path
                    if (!helper.isTypeResolvable(type)) {
                        addProblem(expression, StateFieldPathExpression_NotResolvable, abstractSchemaName);
                        valid = false;
                    }
                    // Not a relationship mapping
                    else if (!helper.isRelationshipMapping(mapping)) {
                        addProblem(expression, PathExpression_NotRelationshipMapping, abstractSchemaName);
                        valid = false;
                    }
                }
                else {
                    addProblem(expression, AbstractSchemaName_Invalid, abstractSchemaName);
                    valid = false;
                }
            }
            // The managed type does not exist
            else {
                addProblem(expression, AbstractSchemaName_Invalid, abstractSchemaName);
                valid = false;
            }
        }

        return valid;
    }

    /**
     * Validates the encapsulated expression of the given addition expression. The test to perform is:
     * <ul>
     * <li>If the left or right expression is a path expression, validation makes sure it is a basic
     * mapping, an association field is not allowed.</li>
     * <li>If the left or right expression is not a path expression, validation will be redirected to
     * that expression but the returned status will not be updated.</li>
     * </ul>
     *
     * @param expression The {@link AdditionExpression} to validate by validating its encapsulated
     * expression
     * @return A number indicating the validation result. {@link #isValid(int, int)} can be used to
     * determine the validation status of an expression based on its position
     */
    protected int validateAdditionExpression(AdditionExpression expression) {
        return validateArithmeticExpression(
            expression,
            AdditionExpression_LeftExpression_WrongType,
            AdditionExpression_RightExpression_WrongType
        );
    }

    /**
     * Validates the given {@link AllOrAnyExpression}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link AllOrAnyExpression} to validate
     */
    protected void validateAllOrAnyExpression(AllOrAnyExpression expression) {
        super.visit(expression);
    }

    /**
     * Validates the given {@link AndExpression}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link AndExpression} to validate
     */
    protected void validateAndExpression(AndExpression expression) {
        super.visit(expression);
    }

    /**
     * Validates the type of the left and right expressions defined by the given {@link ArithmeticExpression}.
     * The test to perform is:
     * <ul>
     * <li>If the encapsulated expression is a path expression, validation makes sure it is a basic
     * mapping, an association field is not allowed.</li>
     * <li>If the encapsulated expression is not a path expression, validation will be redirected to
     * that expression but the returned status will not be changed.</li>
     * </ul>
     *
     * @param expression The {@link ArithmeticExpression} to validate
     * @param leftExpressionWrongTypeMessageKey The key used to describe the left expression does not
     * have a valid type
     * @param rightExpressionWrongTypeMessageKey The key used to describe the right expression does
     * not have a valid type
     * @return A number indicating the validation result. {@link #isValid(int, int)} can be used to
     * determine the validation status of an expression based on its position
     */
    protected int validateArithmeticExpression(ArithmeticExpression expression,
                                               String leftExpressionWrongTypeMessageKey,
                                               String rightExpressionWrongTypeMessageKey) {

        return validateFunctionPathExpression(expression, PathType.BASIC_FIELD_ONLY);
    }

    /**
     * Validates the arithmetic factor expression. The test to perform is:
     * <ul>
     * <li>If the arithmetic factor is a path expression, validation makes sure it is a basic
     * mapping, an association field is not allowed.</li>
     * </ul>
     *
     * @param expression The {@link ArithmeticFactor} to validate
     * @return <code>false</code> if the arithmetic factor expression was validated and is invalid;
     * <code>true</code> otherwise
     */
    protected boolean validateArithmeticExpression(ArithmeticFactor expression) {

        boolean valid = true;

        if (expression.hasExpression()) {
            Expression factor = expression.getExpression();

            // Special case for state field path expression, association field is not allowed
            StateFieldPathExpression pathExpression = getStateFieldPathExpression(factor);

            if (pathExpression != null) {
                valid = validateStateFieldPathExpression(pathExpression, PathType.BASIC_FIELD_ONLY);
            }
            else {
                factor.accept(this);
            }
        }

        return valid;
    }

    /**
     * Validates the encapsulated expression of the given <code><b>AVG</b></code> expression. The
     * test to perform is:
     * <ul>
     * <li>If the encapsulated expression is a path expression, validation makes sure it is a basic
     * mapping, an association field is not allowed.</li>
     * <li>If the encapsulated expression is not a path expression, validation will be redirected to
     * that expression but the returned status will not be changed.</li>
     * </ul>
     *
     * @param expression The {@link AvgFunction} to validate by validating its encapsulated expression
     * @return <code>false</code> if the encapsulated expression was validated and is invalid;
     * <code>true</code> otherwise
     */
    protected boolean validateAvgFunction(AvgFunction expression) {
        return validateFunctionPathExpression(expression);
    }

    /**
     * Validates the given {@link BetweenExpression}. The test to perform is:
     * <ul>
     * <li>If the "first" expression is a path expression, validation makes sure it is a basic
     * mapping, an association field is not allowed.</li>
     * </ul>
     *
     * @param expression The {@link BetweenExpression} to validate
     */
    protected int validateBetweenExpression(BetweenExpression expression) {

        int result = 0;

        // Validate the "first" expression
        if (expression.hasExpression()) {
            Expression firstExpression = expression.getExpression();

            // Special case for state field path expression, association field is not allowed
            StateFieldPathExpression pathExpression = getStateFieldPathExpression(firstExpression);

            if (pathExpression != null) {
                boolean valid = validateStateFieldPathExpression(pathExpression, PathType.BASIC_FIELD_ONLY);
                updateStatus(result, 0, valid);
            }
            else {
                firstExpression.accept(this);
            }
        }

        // Validate the lower bound expression
        expression.getLowerBoundExpression().accept(this);

        // Validate the upper bound expression
        expression.getUpperBoundExpression().accept(this);

        return result;
    }

    /**
     * Validates the given {@link CaseExpression}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link CaseExpression} to validate
     */
    protected void validateCaseExpression(CaseExpression expression) {
        super.visit(expression);
    }

    /**
     * Validates the given {@link CoalesceExpression}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link CoalesceExpression} to validate
     */
    protected void validateCoalesceExpression(CoalesceExpression expression) {
        super.visit(expression);
    }

    /**
     * Validates the given {@link CollectionMemberDeclaration}.
     *
     * @param expression The {@link CollectionMemberDeclaration} to validate
     */
    protected void validateCollectionMemberDeclaration(CollectionMemberDeclaration expression) {

        validateCollectionValuedPathExpression(expression.getCollectionValuedPathExpression(), true);

        try {
            registerIdentificationVariable = false;
            expression.getIdentificationVariable().accept(this);
        }
        finally {
            registerIdentificationVariable = true;
        }
    }

    /**
     * Validates the given {@link CollectionMemberExpression}. Only the collection-valued path
     * expression is validated.
     *
     * @param expression The {@link CollectionMemberExpression} to validate
     * @return A number indicating the validation result. {@link #isValid(int, int)} can be used to
     * determine the validation status of an expression based on its position
     */
    protected int validateCollectionMemberExpression(CollectionMemberExpression expression) {

        int result = 0;

        // Validate the entity expression
        if (expression.hasEntityExpression()) {
            Expression entityExpression = expression.getEntityExpression();

            // Special case for state field path expression, association field is allowed
            StateFieldPathExpression pathExpression = getStateFieldPathExpression(entityExpression);

            if (pathExpression != null) {
                boolean valid = validateStateFieldPathExpression(pathExpression, PathType.ASSOCIATION_FIELD_ONLY);
                updateStatus(result, 0, valid);
            }
            else {
                entityExpression.accept(this);
            }
        }

        // Validate the collection-valued path expression
        boolean valid = validateCollectionValuedPathExpression(expression.getCollectionValuedPathExpression(), true);
        updateStatus(result, 1, valid);

        return result;
    }

    /**
     * Validates the given {@link Expression} and makes sure it's a valid collection value path expression.
     *
     * @param expression The {@link Expression} to validate
     * @param collectionTypeOnly <code>true</code> to make sure the path expression resolves to a
     * collection mapping only; <code>false</code> if it can simply resolves to a relationship mapping
     */
    protected boolean validateCollectionValuedPathExpression(Expression expression,
                                                             boolean collectionTypeOnly) {

        boolean valid = true;

        // The path expression resolves to a collection-valued path expression
        CollectionValuedPathExpression collectionValuedPathExpression = getCollectionValuedPathExpression(expression);

        if (collectionValuedPathExpression != null &&
            collectionValuedPathExpression.hasIdentificationVariable() &&
           !collectionValuedPathExpression.endsWithDot()) {

            // A collection_valued_field is designated by the name of an association field in a
            // one-to-many or a many-to-many relationship or by the name of an element collection field
            Object mapping = helper.resolveMapping(expression);
            Object type = helper.getMappingType(mapping);

            // Does not resolve to a valid path
            if (!helper.isTypeResolvable(type) || (mapping == null)) {

                int startPosition = position(expression);
                int endPosition   = startPosition + length(expression);

                addProblem(
                    expression,
                    startPosition,
                    endPosition,
                    CollectionValuedPathExpression_NotResolvable,
                    expression.toParsedText()
                );

                valid = false;
            }
            else if (collectionTypeOnly && !helper.isCollectionMapping(mapping) ||
                    !collectionTypeOnly && !helper.isRelationshipMapping(mapping)) {

                int startPosition = position(expression);
                int endPosition   = startPosition + length(expression);

                addProblem(
                    expression,
                    startPosition,
                    endPosition,
                    CollectionValuedPathExpression_NotCollectionType,
                    expression.toParsedText()
                );

                valid = false;
            }
        }

        return valid;
    }

    /**
     * Validates the given {@link Expression} and makes sure it's a valid collection value path expression.
     * 
     * join_collection_valued_path_expression::=
     *     identification_variable.{single_valued_embeddable_object_field.}*collection_valued_field
     * join_single_valued_path_expression::=
     *     identification_variable.{single_valued_embeddable_object_field.}*single_valued_object_field
     *
     * @param expression The {@link Expression} to validate
     * @param collectionTypeOnly <code>true</code> to make sure the path expression resolves to a
     * collection mapping only; <code>false</code> if it can simply resolves to a relationship mapping
     */
    protected boolean validateJoinCollectionValuedPathExpression(Expression expression,
                                                             boolean collectionTypeOnly) {

        boolean valid = true;

        // The path expression resolves to a collection-valued path expression
        CollectionValuedPathExpression collectionValuedPathExpression = getCollectionValuedPathExpression(expression);

        if (collectionValuedPathExpression != null &&
            collectionValuedPathExpression.hasIdentificationVariable() &&
           !collectionValuedPathExpression.endsWithDot()) {

            // A collection_valued_field is designated by the name of an association field in a
            // one-to-many or a many-to-many relationship or by the name of an element collection field

            // A single_valued_object_field is designated by the name of an association field in a one-to-one or
            // many-to-one relationship or a field of embeddable class type
            Object mapping = helper.resolveMapping(expression);
            Object type = helper.getMappingType(mapping);

            // Does not resolve to a valid path
            if (!helper.isTypeResolvable(type) || (mapping == null)) {

                int startPosition = position(expression);
                int endPosition   = startPosition + length(expression);

                addProblem(
                    expression,
                    startPosition,
                    endPosition,
                    CollectionValuedPathExpression_NotResolvable,
                    expression.toParsedText()
                );

                valid = false;
            }
            else if (!helper.isCollectionMapping(mapping) && 
                    !helper.isRelationshipMapping(mapping) && 
                    !helper.isEmbeddableMapping(mapping)) {

                int startPosition = position(expression);
                int endPosition   = startPosition + length(expression);

                addProblem(
                    expression,
                    startPosition,
                    endPosition,
                    CollectionValuedPathExpression_NotCollectionType,
                    expression.toParsedText()
                );

                valid = false;
            }
        }

        return valid;
    }

    /**
     * Validates the left and right expressions of the given {@link ComparisonExpression}. The tests
     * to perform are:
     * <ul>
     *    <li>If the comparison operator is either '=' or {@literal '<>'}. The expressions can only be
     *       <ul>
     *          <li>Two identification variables;</li>
     *          <li>Two path expressions resolving to an association field;</li>
     *          <li>One can be a path expression resolving to a basic field and the other one has to
     *              resolve to a basic value.</li>
     *       </ul>
     *    </li>
     *    <li>If the comparison operator is either {@literal '<', '<=', '>=', '>'}. The expressions cannot be
     *       <ul>
     *          <li>Two identification variables;</li>
     *          <li>Two path expressions resolving to an association field;</li>
     *       </ul>
     *    </li>
     * </ul>
     *
     * @param expression The {@link ConcatExpression} to validate by validating its
     * left and right expressions
     * @return The status of the comparison between the left and right expression: <code>true</code>
     * if the two expressions pass the rules defined by this method; <code>false</code> otherwise
     */
    protected boolean validateComparisonExpression(ComparisonExpression expression) {

        Expression leftExpression  = expression.getLeftExpression();
        Expression rightExpression = expression.getRightExpression();
        boolean valid = true;

        // First determine what is being compared and validate them as well
        ComparisonExpressionVisitor validator = getComparisonExpressionVisitor();

        try {
            // Visit the left expression and gather its information
            validator.validatingLeftExpression = true;
            leftExpression.accept(validator);

            // Visit the right expression and gather its information
            validator.validatingLeftExpression = false;
            rightExpression.accept(validator);

            // '<', '<=', '>=', '>'
            if (isOrderComparison(expression)) {

                // The left expression cannot be an identification variable
                if (validator.leftIdentificationVariable &&
                    validator.leftIdentificationVariableValid) {

                    IdentificationVariable variable = (IdentificationVariable) leftExpression;

                    // There is a specific EclipseLink case where it is valid to use an
                    // identification variable, which is when the identification variable
                    // maps to a direct collection mapping
                    if (!isIdentificationVariableValidInComparison(variable)) {

                        addProblem(
                            leftExpression,
                            ComparisonExpression_IdentificationVariable,
                            leftExpression.toActualText(),
                            expression.getComparisonOperator()
                        );

                        valid = false;
                    }
                }
                // The left expression is a path expression
                else if (validator.leftStateFieldPathExpression &&
                         validator.leftStateFieldPathExpressionValid) {

                    Object mapping = helper.resolveMapping(leftExpression);

                    // The path expression cannot be a non-basic mapping
                    if ((mapping != null) && !helper.isPropertyMapping(mapping)) {

                        addProblem(
                            leftExpression,
                            ComparisonExpression_AssociationField,
                            leftExpression.toActualText(),
                            expression.getComparisonOperator()
                        );

                        valid = false;
                    }
                }

                // The right expression cannot be an identification variable
                if (validator.rightIdentificationVariable &&
                    validator.rightIdentificationVariableValid) {

                    IdentificationVariable variable = (IdentificationVariable) rightExpression;

                    // There is a specific EclipseLink case where it is valid to use an
                    // identification variable, which is when the identification variable
                    // maps to a direct collection mapping
                    if (!isIdentificationVariableValidInComparison(variable)) {

                        addProblem(
                            rightExpression,
                            ComparisonExpression_IdentificationVariable,
                            rightExpression.toActualText(),
                            expression.getComparisonOperator()
                        );

                        valid = false;
                    }
                }
                // The right expression is a path expression
                else if (validator.rightStateFieldPathExpression      &&
                         validator.rightStateFieldPathExpressionValid) {

                    Object mapping = helper.resolveMapping(rightExpression);

                    // The path expression cannot be a non-basic mapping
                    if ((mapping != null) && !helper.isPropertyMapping(mapping)) {

                        addProblem(
                            rightExpression,
                            ComparisonExpression_AssociationField,
                            rightExpression.toActualText(),
                            expression.getComparisonOperator()
                        );

                        valid = false;
                    }
                }
            }
            // '=', '<>'
            else {

                // The left expression is an identification variable
                // The right expression is a path expression
                if (validator.leftIdentificationVariable      &&
                    validator.leftIdentificationVariableValid &&
                    validator.rightStateFieldPathExpression   &&
                    validator.rightStateFieldPathExpressionValid) {

                    Object mapping = helper.resolveMapping(rightExpression);
                    IdentificationVariable variable = (IdentificationVariable) leftExpression;

                    // The path expression can only be a non-basic mapping.
                    // There is a specific EclipseLink case where it is valid to use an
                    // identification variable, which is when the identification variable
                    // maps to a direct collection mapping
                    if ((mapping != null) && helper.isPropertyMapping(mapping) &&
                        !isIdentificationVariableValidInComparison(variable)) {

                        addProblem(
                            rightExpression,
                            ComparisonExpression_BasicField,
                            rightExpression.toActualText(),
                            expression.getComparisonOperator()
                        );

                        valid = false;
                    }
                }
                // The left expression is a path expression
                // The right expression is an identification variable
                else if (validator.rightIdentificationVariable      &&
                         validator.rightIdentificationVariableValid &&
                         validator.leftStateFieldPathExpression     &&
                         validator.leftStateFieldPathExpressionValid) {

                    Object mapping = helper.resolveMapping(leftExpression);
                    IdentificationVariable variable = (IdentificationVariable) rightExpression;

                    // The path expression can only be a non-basic mapping.
                    // There is a specific EclipseLink case where it is valid to use an
                    // identification variable, which is when the identification variable
                    // maps to a direct collection mapping
                    if ((mapping != null) && helper.isPropertyMapping(mapping) &&
                        !isIdentificationVariableValidInComparison(variable)) {

                        addProblem(
                            leftExpression,
                            ComparisonExpression_BasicField,
                            leftExpression.toActualText(),
                            expression.getComparisonOperator()
                        );

                        valid = false;
                    }
                }
            }

            return valid;
        }
        finally {
            validator.dispose();
        }
    }

    /**
     * Validates the encapsulated expression of the given <code><b>CONCAT</b></code> expression.
     * The tests to perform are:
     * <ul>
     *    <li>If the encapsulated expression is a path expression, validation makes sure it is a
     *        basic mapping, an association field is not allowed.</li>
     *    <li>If the encapsulated expression is not a path expression, validation will be redirected
     *        to that expression but the returned status will not be changed.</li>
     * </ul>
     *
     * @param expression The {@link ConcatExpression} to validate by validating its encapsulated expression
     * @return <code>false</code> if the first encapsulated expression was validated and is invalid;
     * <code>true</code> otherwise
     */
    protected boolean validateConcatExpression(ConcatExpression expression) {
        return validateFunctionPathExpression(expression);
    }

    /**
     * Validates the given {@link ConstructorExpression}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link ConstructorExpression} to validate
     */
    protected void validateConstructorExpression(ConstructorExpression expression) {
        super.visit(expression);
    }

    /**
     * Validates the given {@link CountFunction}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link CountFunction} to validate
     */
    protected void validateCountFunction(CountFunction expression) {

        if (expression.hasExpression()) {

            Expression leftExpression = expression.getExpression();
            StateFieldPathExpression pathExpression = getStateFieldPathExpression(leftExpression);

            if (pathExpression != null) {
                validateStateFieldPathExpression(pathExpression, validPathExpressionTypeForCountFunction());
            }
            else {
                leftExpression.accept(this);
            }
        }
    }

    /**
     * Validates the given {@link DateTime}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link DateTime} to validate
     */
    protected void validateDateTime(DateTime expression) {
        super.visit(expression);
    }

    /**
     * Validates the given {@link DeleteClause}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link DeleteClause} to validate
     */
    protected void validateDeleteClause(DeleteClause expression) {
        super.visit(expression);
    }

    /**
     * Validates the given {@link DeleteStatement}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link DeleteStatement} to validate
     */
    protected void validateDeleteStatement(DeleteStatement expression) {
        super.visit(expression);
    }

    /**
     * Validates the encapsulated expression of the given division expression. The test to perform is:
     * <ul>
     * <li>If the left or right expression is a path expression, validation makes sure it is a basic
     * mapping, an association field is not allowed.</li>
     * <li>If the left or right expression is not a path expression, validation will be redirected to
     * that expression but the returned status will not be updated.</li>
     * </ul>
     *
     * @param expression The {@link DivisionExpression} to validate by validating its encapsulated
     * expression
     * @return A number indicating the validation result. {@link #isValid(int, int)} can be used to
     * determine the validation status of an expression based on its position
     */
    protected int validateDivisionExpression(DivisionExpression expression) {
        return validateArithmeticExpression(
            expression,
            DivisionExpression_LeftExpression_WrongType,
            DivisionExpression_RightExpression_WrongType
        );
    }

    protected boolean validateEntityTypeLiteral(EntityTypeLiteral expression) {

        String entityTypeName = expression.getEntityTypeName();
        boolean valid = true;

        if (ExpressionTools.stringIsNotEmpty(entityTypeName)) {
            Object entity = helper.getEntityNamed(entityTypeName);

            if (entity == null) {
                int startIndex = position(expression);
                int endIndex   = startIndex + entityTypeName.length();
                addProblem(expression, startIndex, endIndex, EntityTypeLiteral_NotResolvable, entityTypeName);
                valid = false;
            }
        }

        return valid;
    }

    /**
     * Validates the given {@link EntryExpression}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link EntryExpression} to validate
     */
    protected void validateEntryExpression(EntryExpression expression) {
        super.visit(expression);
    }

    /**
     * Validates the given {@link ExistsExpression}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link ExistsExpression} to validate
     */
    protected void validateExistsExpression(ExistsExpression expression) {
        super.visit(expression);
    }

    protected void validateFirstDeclaration(AbstractFromClause expression,
                                            JPQLQueryDeclaration declaration,
                                            FirstDeclarationVisitor visitor) {

        Expression declarationExpression = declaration.getDeclarationExpression();
        Expression baseExpression = declaration.getBaseExpression();

        try {
            baseExpression.accept(visitor);

            if (!visitor.valid) {

                int startPosition = position(declarationExpression);
                int endPosition = startPosition + length(declarationExpression);

                addProblem(
                    expression,
                    startPosition,
                    endPosition,
                    AbstractFromClause_InvalidFirstIdentificationVariableDeclaration,
                    baseExpression.toActualText()
                );
            }
            else {
                declarationExpression.accept(this);
            }
        }
        finally {
            visitor.valid = false;
        }
    }

    /**
     * Validates the given {@link FromClause}.
     *
     * @param expression The {@link FromClause} to validate
     */
    protected void validateFromClause(FromClause expression) {
        validateAbstractFromClause(expression, topLevelFirstDeclarationVisitor());
    }

    /**
     * Validates the given {@link FunctionExpression}.
     *
     * @param expression The {@link FunctionExpression} to validate
     */
    protected void validateFunctionExpression(FunctionExpression expression) {
    }

    /**
     * Validates the given {@link AbstractSingleEncapsulatedExpression}'s encapsulated expression if
     * it is a state field path expression and makes sure it is mapping to a basic mapping. That
     * means relationship field mapping is not allowed.
     *
     * @param expression The {@link AbstractSingleEncapsulatedExpression} to validate its encapsulated
     * expression if it's a state field path expression, otherwise does nothing
     * @return <code>false</code> if the encapsulated expression was validated and is invalid;
     * <code>true</code> otherwise
     */
    protected boolean validateFunctionPathExpression(AbstractSingleEncapsulatedExpression expression) {

        boolean valid = true;

        if (expression.hasEncapsulatedExpression()) {
            Expression encapsulatedExpression = expression.getExpression();

            // Special case for state field path expression, association field is not allowed
            StateFieldPathExpression pathExpression = getStateFieldPathExpression(encapsulatedExpression);

            if (pathExpression != null) {
                valid = validateStateFieldPathExpression(pathExpression, PathType.BASIC_FIELD_ONLY);
            }
            else {
                encapsulatedExpression.accept(this);
            }
        }

        return valid;
    }

    /**
     * Validates the left and right expressions of the given compound expression. The test to perform is:
     * <ul>
     * <li>If the left or the right expression is a path expression, validation makes sure it is a
     * basic mapping, an association field is not allowed.</li>
     * </ul>
     *
     * @param expression The {@link CompoundExpression} to validate by validating its left and right
     * expressions
     * @param pathType The type of field that is allowed
     * @return A number indicating the validation result. {@link #isValid(int, int)} can be used to
     * determine the validation status of an expression based on its position
     */
    protected int validateFunctionPathExpression(CompoundExpression expression, PathType pathType) {

        int result = 0;

        // Left expression
        if (expression.hasLeftExpression()) {
            Expression leftExpression = expression.getLeftExpression();
            StateFieldPathExpression pathExpression = getStateFieldPathExpression(leftExpression);
            if (pathExpression != null) {
                boolean valid = validateStateFieldPathExpression(pathExpression, pathType);
                updateStatus(result, 0, valid);
            }
            else {
                leftExpression.accept(this);
            }
        }

        // Right expression
        if (expression.hasRightExpression()) {
            Expression rightExpression = expression.getRightExpression();
            StateFieldPathExpression pathExpression = getStateFieldPathExpression(rightExpression);
            if (pathExpression != null) {
                boolean valid = validateStateFieldPathExpression(pathExpression, pathType);
                updateStatus(result, 1, valid);
            }
            else {
                rightExpression.accept(this);
            }
        }

        return result;
    }

    /**
     * Validates the given {@link GroupByClause}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link GroupByClause} to validate
     */
    protected void validateGroupByClause(GroupByClause expression) {
        super.visit(expression);
    }

    /**
     * Validates the given {@link HavingClause}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link HavingClause} to validate
     */
    protected void validateHavingClause(HavingClause expression) {
        super.visit(expression);
    }

    /**
     * Validates the given {@link IdentificationVariable}. The test to perform are:
     * <ul>
     *    <li>If the identification variable resolves to an entity type literal, then no validation
     *        is performed.</li>
     *    <li></li>
     * </ul>
     *
     * @param expression The identification variable to be validated
     * @return <code>true</code> if the given identification variable is valid; <code>false</code>
     * otherwise
     */
    protected boolean validateIdentificationVariable(IdentificationVariable expression) {

        boolean valid = true;

        // Only a non-virtual identification variable is validated
        if (!expression.isVirtual()) {

            String variable = expression.getText();
            boolean continueValidating = true;

            // A entity literal type is parsed as an identification variable, check for that case
            if (isComparingEntityTypeLiteral(expression)) {

                // The identification variable (or entity type literal) does not
                // correspond to an entity name, then continue validation
                Object entity = helper.getEntityNamed(variable);
                continueValidating = (entity == null);
            }

            // Validate a real identification variable
            if (continueValidating) {

                if (registerIdentificationVariable) {
                    usedIdentificationVariables.add(expression);
                }

                valid = validateIdentificationVariable(expression, variable);
            }
        }
        // The identification variable actually represents a state field path expression that has
        // a virtual identification, validate that state field path expression instead
        else {
            StateFieldPathExpression pathExpression = expression.getStateFieldPathExpression();

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

        return valid;
    }

    /**
     * Validates the given identification variable. The default behavior is to not validate it.
     *
     * @param expression The {@link IdentificationVariable} that is being visited
     * @param variable The actual identification variable, which is never an empty string
     * @return <code>true</code> if the given identification variable is valid; <code>false</code>
     * otherwise
     */
    protected boolean validateIdentificationVariable(IdentificationVariable expression, String variable) {
        return true;
    }

    /**
     * Validates the given {@link InExpression}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link InExpression} to validate
     */
    protected void validateIdentificationVariableDeclaration(IdentificationVariableDeclaration expression) {
        super.visit(expression);
    }

    /**
     * Validates the identification variables:
     * <ul>
     * <li>Assures those used throughout the query have been defined in the <code><b>FROM</b></code>
     * clause in the current subquery or in a superquery.</li>
     * <li>They have been defined only once.</li>
     * </ul>
     */
    protected void validateIdentificationVariables() {

        // Collect the identification variables from the Declarations
        Map<String, List<IdentificationVariable>> identificationVariables = new HashMap<>();
        helper.collectLocalDeclarationIdentificationVariables(identificationVariables);

        // Check for duplicate identification variables
        for (Map.Entry<String, List<IdentificationVariable>> entry : identificationVariables.entrySet()) {

            List<IdentificationVariable> variables = entry.getValue();

            // More than one identification variable was used in a declaration
            if (variables.size() > 1) {
                for (IdentificationVariable variable : variables) {
                    addProblem(variable, IdentificationVariable_Invalid_Duplicate, variable.getText());
                }
            }
        }

        // Now collect the identification variables from the parent queries
        identificationVariables.clear();
        helper.collectAllDeclarationIdentificationVariables(identificationVariables);

        // Check for undeclared identification variables
        for (IdentificationVariable identificationVariable : usedIdentificationVariables) {
            String variableName = identificationVariable.getText();

            if (ExpressionTools.stringIsNotEmpty(variableName) &&
                !identificationVariables.containsKey(variableName.toUpperCase(Locale.ROOT))) {

                addProblem(identificationVariable, IdentificationVariable_Invalid_NotDeclared, variableName);
            }
        }
    }

    /**
     * Validates the given {@link IndexExpression}. It validates the identification variable and
     * makes sure is it defined in <code><b>IN</b></code> or <code><b>IN</b></code> expression.
     *
     * @param expression The {@link IndexExpression} to validate
     */
    protected boolean validateIndexExpression(IndexExpression expression) {

        boolean valid = true;

        // The INDEX function can only be applied to identification variables denoting types for
        // which an order column has been specified
        String variableName = literal(
            expression.getExpression(),
            LiteralType.IDENTIFICATION_VARIABLE
        );

        // The identification variable is not defined in a JOIN or IN expression
        if (ExpressionTools.stringIsNotEmpty(variableName) &&
            !helper.isCollectionIdentificationVariable(variableName)) {

            addProblem(expression.getExpression(), IndexExpression_WrongVariable, variableName);
            valid = false;
        }

        return valid;
    }

    /**
     * Validates the given {@link InExpression}. The test to perform is:
     * <ul>
     * <li>If the expression is a path expression, validation makes sure it is an association mapping,
     * a basic field is not allowed.</li>
     * </ul>
     *
     * @param expression The {@link InExpression} to validate
     */
    protected void validateInExpression(InExpression expression) {

        // Validate the left expression
        if (expression.hasExpression()) {
            Expression stringExpression = expression.getExpression();

            // Special case for state field path expression
            StateFieldPathExpression pathExpression = getStateFieldPathExpression(stringExpression);

            if (pathExpression != null) {
                validateStateFieldPathExpression(pathExpression, validPathExpressionTypeForInExpression());
            }
            else {
                stringExpression.accept(this);
            }
        }

        // Validate the items
        expression.getInItems().accept(getInItemsVisitor());
    }

    /**
     * Validates the given {@link Join}.
     *
     * @param expression The {@link ValueExpression} to validate
     */
    protected void validateJoin(Join expression) {

        if (expression.hasJoinAssociationPath()) {
            Expression joinAssociationPath = expression.getJoinAssociationPath();
            validateJoinCollectionValuedPathExpression(joinAssociationPath, false);
            joinAssociationPath.accept(this);
        }

        if (expression.hasIdentificationVariable()) {
            try {
                registerIdentificationVariable = false;
                expression.getIdentificationVariable().accept(this);
            }
            finally {
                registerIdentificationVariable = true;
            }
        }
    }

    protected void validateJoinsIdentificationVariable(AbstractFromClause expression,
                                                       List<JPQLQueryDeclaration> declarations,
                                                       JPQLQueryDeclaration declaration,
                                                       int index) {

        List<Join> joins = declaration.getJoins();

        for (int joinIndex = 0, joinCount = joins.size(); joinIndex < joinCount; joinIndex++) {

            Join join = joins.get(joinIndex);

            // Retrieve the identification variable from the join association path
            String variableName = literal(
                join.getJoinAssociationPath(),
                LiteralType.PATH_EXPRESSION_IDENTIFICATION_VARIABLE
            );

            // Make sure the identification variable is defined before the JOIN expression
            if (ExpressionTools.stringIsNotEmpty(variableName) &&
                isIdentificationVariableDeclaredAfter(variableName, index, joinIndex, declarations)) {

                int startPosition = position(join.getJoinAssociationPath());
                int endPosition   = startPosition + variableName.length();

                addProblem(
                    expression,
                    startPosition,
                    endPosition,
                    AbstractFromClause_WrongOrderOfIdentificationVariableDeclaration,
                    variableName
                );
            }
        }
    }

    /**
     * Validates the given {@link KeyExpression}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link KeyExpression} to validate
     */
    protected void validateKeyExpression(KeyExpression expression) {
        super.visit(expression);
    }

    /**
     * Validates the encapsulated expression of the given <code><b>LENGTH</b></code> expression. The
     * test to perform is:
     * <ul>
     * <li>If the encapsulated expression is a path expression, validation makes sure it is a basic
     * mapping, an association field is not allowed.</li>
     * <li>If the encapsulated expression is not a path expression, validation will be redirected to
     * that expression but the returned status will not be changed.</li>
     * </ul>
     *
     * @param expression The {@link LengthExpression} to validate by validating its encapsulated expression
     * @return <code>false</code> if the encapsulated expression was validated and is invalid;
     * <code>true</code> otherwise
     */
    protected boolean validateLengthExpression(LengthExpression expression) {
        return validateFunctionPathExpression(expression);
    }

    /**
     * Validates the string expression of the given <code><b>LIKE</b></code> expression. The test to
     * perform is:
     * <ul>
     * <li>If the string expression is a path expression, validation makes sure it is a basic
     * mapping, an association field is not allowed.</li>
     * <li>If the encapsulated expression is not a path expression, validation will be redirected to
     * that expression but the returned status will not be changed.</li>
     * </ul>
     *
     * @param expression The {@link LengthExpression} to validate by validating its string expression
     * @return A number indicating the validation result. {@link #isValid(int, int)} can be used to
     * determine the validation status of an expression based on its position
     */
    protected int validateLikeExpression(LikeExpression expression) {

        int result = 0;

        // Validate the "first" expression
        if (expression.hasStringExpression()) {
            Expression stringExpression = expression.getStringExpression();

            // Special case for state field path expression, association field is not allowed
            StateFieldPathExpression pathExpression = getStateFieldPathExpression(stringExpression);

            if (pathExpression != null) {
                boolean valid = validateStateFieldPathExpression(pathExpression, validPathExpressionTypeForStringExpression());
                updateStatus(result, 0, valid);
            }
            else {
                stringExpression.accept(this);
            }
        }

        // Validate the pattern value
        expression.getPatternValue().accept(this);

        // Validate the escape character
        expression.getEscapeCharacter().accept(this);

        return result;
    }

    /**
     * Validates the encapsulated expression of the given <code><b>LOCATE</b></code> expression. The
     * test to perform is:
     * <ul>
     * <li>If the encapsulated expression is a path expression, validation makes sure it is a basic
     * mapping, an association field is not allowed.</li>
     * <li>If the encapsulated expression is not a path expression, validation will be redirected to
     * that expression but the returned status will not be changed.</li>
     * </ul>
     *
     * @param expression The {@link LocateExpression} to validate by validating its encapsulated expression
     * @return A number indicating the validation result. {@link #isValid(int, int)} can be used to
     * determine the validation status of an expression based on its position
     */
    protected int validateLocateExpression(LocateExpression expression) {

        int result = 0;

        // Validate the first expression
        if (expression.hasFirstExpression()) {
            Expression firstExpression = expression.getFirstExpression();

            // Special case for state field path expression, association field is not allowed
            StateFieldPathExpression pathExpression = getStateFieldPathExpression(firstExpression);

            if (pathExpression != null) {
                boolean valid = validateStateFieldPathExpression(pathExpression, PathType.BASIC_FIELD_ONLY);
                updateStatus(result, 0, valid);
            }
            else {
                firstExpression.accept(this);
            }
        }

        // Validate the second expression
        expression.getSecondExpression().accept(this);

        // Validate the third expression
        expression.getThirdExpression().accept(this);

        return result;
    }

    /**
     * Validates the encapsulated expression of the given <code><b>LOWER</b></code> expression. The
     * test to perform is:
     * <ul>
     * <li>If the encapsulated expression is a path expression, validation makes sure it is a basic
     * mapping, an association field is not allowed.</li>
     * <li>If the encapsulated expression is not a path expression, validation will be redirected to
     * that expression but the returned status will not be changed.</li>
     * </ul>
     *
     * @param expression The {@link LowerExpression} to validate by validating its encapsulated expression
     * @return <code>false</code> if the encapsulated expression was validated and is invalid;
     * <code>true</code> otherwise
     */
    protected boolean validateLowerExpression(LowerExpression expression) {
        return validateFunctionPathExpression(expression);
    }

    /**
     * Validates the encapsulated expression of the given <code><b>MAX</b></code> expression. The
     * test to perform is:
     * <ul>
     * <li>If the encapsulated expression is a path expression, validation makes sure it is a basic
     * mapping, an association field is not allowed.</li>
     * <li>If the encapsulated expression is not a path expression, validation will be redirected to
     * that expression but the returned status will not be changed.</li>
     * </ul>
     *
     * @param expression The {@link MaxFunction} to validate by validating its encapsulated expression
     * @return <code>false</code> if the encapsulated expression was validated and is not valid;
     * <code>true</code> otherwise
     */
    protected boolean validateMaxFunction(MaxFunction expression) {
        // Arguments to the functions MAX must correspond to orderable state field types (i.e.,
        // numeric types, string types, character types, or date types)
        return validateFunctionPathExpression(expression);
    }

    /**
     * Validates the encapsulated expression of the given <code><b>MIN</b></code> expression. The
     * test to perform is:
     * <ul>
     * <li>If the encapsulated expression is a path expression, validation makes sure it is a basic
     * mapping, an association field is not allowed.</li>
     * <li>If the encapsulated expression is not a path expression, validation will be redirected to
     * that expression but the returned status will not be changed.</li>
     * </ul>
     *
     * @param expression The {@link MinFunction} to validate by validating its encapsulated expression
     * @return <code>false</code> if the encapsulated expression was validated and is not valid;
     * <code>true</code> otherwise
     */
    protected boolean validateMinFunction(MinFunction expression) {
        // Arguments to the functions MIN must correspond to orderable state field types (i.e.,
        // numeric types, string types, character types, or date types)
        return validateFunctionPathExpression(expression);
    }

    /**
     * Validates the encapsulated expression of the given <code><b>MOD</b></code> expression. The
     * test to perform is:
     * <ul>
     * <li>If the encapsulated expression is a path expression, validation makes sure it is a basic
     * mapping, an association field is not allowed.</li>
     * <li>If the encapsulated expression is not a path expression, validation will be redirected to
     * that expression but the returned status will not be changed.</li>
     * </ul>
     *
     * @param expression The {@link ModExpression} to validate by validating its encapsulated expression
     * @return A number indicating the validation result. {@link #isValid(int, int)} can be used to
     * determine the validation status of an expression based on its position
     */
    protected int validateModExpression(ModExpression expression) {

        int result = 0;

        // Validate the first expression
        if (expression.hasFirstExpression()) {
            Expression firstExpression = expression.getFirstExpression();

            // Special case for state field path expression, association field is not allowed
            StateFieldPathExpression pathExpression = getStateFieldPathExpression(firstExpression);

            if (pathExpression != null) {
                boolean valid = validateStateFieldPathExpression(pathExpression, PathType.BASIC_FIELD_ONLY);
                updateStatus(result, 0, valid);
            }
            else {
                firstExpression.accept(this);
            }
        }

        // Validate the second expression
        expression.getSecondExpression().accept(this);

        return result;
    }

    /**
     * Validates the encapsulated expression of the given multiplication expression. The test to
     * perform is:
     * <ul>
     * <li>If the left or right expression is a path expression, validation makes sure it is a basic
     * mapping, an association field is not allowed.</li>
     * <li>If the left or right expression is not a path expression, validation will be redirected to
     * that expression but the returned status will not be updated.</li>
     * </ul>
     *
     * @param expression The {@link MultiplicationExpression} to validate by validating its encapsulated
     * expression
     * @return A number indicating the validation result. {@link #isValid(int, int)} can be used to
     * determine the validation status of an expression based on its position
     */
    protected int validateMultiplicationExpression(MultiplicationExpression expression) {
        return validateArithmeticExpression(
            expression,
            MultiplicationExpression_LeftExpression_WrongType,
            MultiplicationExpression_RightExpression_WrongType
        );
    }

    /**
     * Validates the given {@link NotExpression}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link NotExpression} to validate
     */
    protected void validateNotExpression(NotExpression expression) {
        super.visit(expression);
    }

    /**
     * Validates the given {@link NullComparisonExpression}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link NullComparisonExpression} to validate
     */
    protected void validateNullComparisonExpression(NullComparisonExpression expression) {
        super.visit(expression);
    }

    /**
     * Validates the given {@link NullIfExpression}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link NullIfExpression} to validate
     */
    protected void validateNullIfExpression(NullIfExpression expression) {
        super.visit(expression);
    }

    /**
     * Validates the given {@link ObjectExpression}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link ObjectExpression} to validate
     */
    protected void validateObjectExpression(ObjectExpression expression) {
        super.visit(expression);
    }

    /**
     * Validates the given {@link OnClause}. The default behavior does not require to semantically
     * validate it.
     *
     * @param expression The {@link OnClause} to validate
     */
    protected void validateOnClause(OnClause expression) {
        super.visit(expression);
    }

    /**
     * Validates the given {@link OrderByItem}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link OrderByItem} to validate
     */
    protected void validateOrderByClause(OrderByClause expression) {
        super.visit(expression);
    }

    /**
     * Validates the given {@link OrderByItem}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link OrderByItem} to validate
     */
    protected void validateOrderByItem(OrderByItem expression) {
        super.visit(expression);
    }

    /**
     * Validates the given {@link OrExpression}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link OrExpression} to validate
     */
    protected void validateOrExpression(OrExpression expression) {
        super.visit(expression);
    }

    /**
     * Validates the given {@link RangeVariableDeclaration}.
     *
     * @param expression The {@link RangeVariableDeclaration} to validate
     */
    protected void validateRangeVariableDeclaration(RangeVariableDeclaration expression) {

        validateRangeVariableDeclarationRootObject(expression);

        try {
            registerIdentificationVariable = false;
            expression.getIdentificationVariable().accept(this);
        }
        finally {
            registerIdentificationVariable = true;
        }
    }

    /**
     * Validates the "root" object of the given {@link RangeVariableDeclaration}.
     *
     * @param expression The {@link RangeVariableDeclaration} that needs its "root" object
     * to be validated
     */
    protected void validateRangeVariableDeclarationRootObject(RangeVariableDeclaration expression) {
        expression.getRootObject().accept(this);
    }

    /**
     * Validates the given {@link ResultVariable}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link ResultVariable} to validate
     */
    protected void validateResultVariable(ResultVariable expression) {
        // TODO: Validate identification to make sure it does not
        //       collide with one defined in the FROM clause
        super.visit(expression);
    }

    /**
     * Validates the given {@link SelectClause}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link SelectClause} to validate
     */
    protected void validateSelectClause(SelectClause expression) {

        Expression selectExpression = expression.getSelectExpression();

        // Special case for state field path expression, all types are allowed
        StateFieldPathExpression pathExpression = getStateFieldPathExpression(selectExpression);

        if (pathExpression != null) {
            validateStateFieldPathExpression(pathExpression, selectClausePathExpressionPathType());
        }
        else {
            selectExpression.accept(this);
        }
    }

    /**
     * Validates the given {@link SelectStatement}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link SelectStatement} to validate
     */
    protected void validateSelectStatement(SelectStatement expression) {
        super.visit(expression);
    }

    /**
     * Validates the given {@link SimpleFromClause}.
     *
     * @param expression The {@link SimpleFromClause} to validate
     */
    protected void validateSimpleFromClause(SimpleFromClause expression) {
        validateAbstractFromClause(expression, subqueryFirstDeclarationVisitor());
    }

    /**
     * Validates the given {@link SimpleSelectClause}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link SimpleSelectClause} to validate
     */
    protected void validateSimpleSelectClause(SimpleSelectClause expression) {
        super.visit(expression);
    }

    protected void validateSimpleSelectStatement(SimpleSelectStatement expression) {

        // Keep a copy of the identification variables that are used throughout the parent query
        List<IdentificationVariable> oldUsedIdentificationVariables = new ArrayList<>(usedIdentificationVariables);

        // Create a context for the subquery
        helper.newSubqueryContext(expression);

        try {
            super.visit(expression);

            // Validate the identification variables that are used within the subquery
            validateIdentificationVariables();
        }
        finally {
            // Revert back to the parent context
            helper.disposeSubqueryContext();

            // Revert the list to what it was
            usedIdentificationVariables.retainAll(oldUsedIdentificationVariables);
        }
    }

    /**
     * Validates the given {@link SizeExpression}.
     *
     * @param expression The {@link SizeExpression} to validate
     * @return <code>false</code> if the encapsulated expression is a collection-valued path expression
     * and it was found to be invalid; <code>true</code> otherwise
     */
    protected boolean validateSizeExpression(SizeExpression expression) {
        // The SIZE function returns an integer value, the number of elements of the collection
        return validateCollectionValuedPathExpression(expression.getExpression(), true);
    }

    /**
     * Validates the encapsulated expression of the given <code><b>SQRT</b></code> expression. The
     * test to perform is:
     * <ul>
     * <li>If the encapsulated expression is a path expression, validation makes sure it is a basic
     * mapping, an association field is not allowed.</li>
     * <li>If the encapsulated expression is not a path expression, validation will be redirected to
     * that expression but the returned status will not be changed.</li>
     * </ul>
     *
     * @param expression The {@link SqrtExpression} to validate by validating its encapsulated expression
     * @return <code>false</code> if the encapsulated expression was validated and is invalid;
     * <code>true</code> otherwise
     */
    protected boolean validateSqrtExpression(SqrtExpression expression) {
        return validateFunctionPathExpression(expression);
    }

    /**
     * Validates the given {@link StateFieldPathExpression}.
     *
     * @param expression The {@link StateFieldPathExpression} the validate
     * @param pathType The type of field that is allowed
     * @return <code>true</code> if the given {@link StateFieldPathExpression} resolves to a valid
     * path; <code>false</code> otherwise
     */
    protected boolean validateStateFieldPathExpression(StateFieldPathExpression expression,
                                                       PathType pathType) {

        boolean valid = true;

        if (expression.hasIdentificationVariable()) {
            expression.getIdentificationVariable().accept(this);

            // A single_valued_object_field is designated by the name of an association field in a
            // one-to-one or many-to-one relationship or a field of embeddable class type
            if (!expression.endsWithDot()) {

                Object mapping = helper.resolveMapping(expression);

                // Validate the mapping
                if (mapping != null) {

                    // It is syntactically illegal to compose a path expression from a path expression
                    // that evaluates to a collection
                    if (helper.isCollectionMapping(mapping)) {
                        if (pathType != PathType.ANY_FIELD_INCLUDING_COLLECTION) {
                            addProblem(expression, StateFieldPathExpression_CollectionType, expression.toActualText());
                            valid = false;
                        }
                    }
                    // A transient mapping is not allowed
                    else if (helper.isTransient(mapping)) {
                        addProblem(expression, StateFieldPathExpression_NoMapping, expression.toParsedText());
                        valid = false;
                    }
                    // Only a basic field is allowed
                    else if ((pathType == PathType.BASIC_FIELD_ONLY) &&
                             !helper.isPropertyMapping(mapping)) {

                        addProblem(expression, StateFieldPathExpression_AssociationField, expression.toActualText());
                        valid = false;
                    }
                    // Only an association field is allowed
                    else if ((pathType == PathType.ASSOCIATION_FIELD_ONLY) &&
                             helper.isPropertyMapping(mapping)) {

                        addProblem(expression, StateFieldPathExpression_BasicField, expression.toActualText());
                        valid = false;
                    }
                }
                // Attempts to resolve something that does not represent a mapping
                else {

                    Object type = helper.getType(expression.toParsedText(0, expression.pathSize() - 1));

                    // An enum constant could have been parsed as a state field path expression
                    if (helper.isEnumType(type)) {

                        // Search for the enum constant
                        String enumConstant = expression.getPath(expression.pathSize() - 1);
                        boolean found = false;

                        for (String constant : helper.getEnumConstants(type)) {
                            if (constant.equals(enumConstant)) {
                                found = true;
                                break;
                            }
                        }

                        if (!found) {
                            int startIndex = position(expression) + helper.getTypeName(type).length() + 1;
                            int endIndex   = startIndex + enumConstant.length();
                            addProblem(expression, startIndex, endIndex, StateFieldPathExpression_InvalidEnumConstant, enumConstant);
                            valid = false;
                        }

                        // Remove the used identification variable since it is the first
                        // package name of the fully qualified enum constant
                        usedIdentificationVariables.remove(expression.getIdentificationVariable());
                    }
                    else {

                        // Special case for EclipseLink, path expression formed with the identification variable
                        // mapped to a subquery or database table cannot be resolved, thus cannot be validated
                        Boolean status = validateThirdPartyStateFieldPathExpression(expression);

                        // Third path extension validated the path expression
                        if (status != null) {
                            valid = status;
                        }
                        // Third path extension did not validate the path expression, continue validating it
                        else {
                            type = helper.getType(expression);

                            // Does not resolve to a valid path
                            if (!helper.isTypeResolvable(type)) {
                                addProblem(expression, StateFieldPathExpression_NotResolvable, expression.toActualText());
                                valid = false;
                            }
                            // No mapping can be found for that path
                            else {
                                addProblem(expression, StateFieldPathExpression_NoMapping, expression.toActualText());
                                valid = false;
                            }
                        }
                    }
                }
            }
        }

        return valid;
    }

    /**
     * Validates the encapsulated expression of the given <code><b>SUBSTRING</b></code> expression.
     * The test to perform is:
     * <ul>
     * <li>If the encapsulated expression is a path expression, validation makes sure it is a basic
     * mapping, an association field is not allowed.</li>
     * <li>If the encapsulated expression is not a path expression, validation will be redirected to
     * that expression but the returned status will not be changed.</li>
     * </ul>
     *
     * @param expression The {@link SubstringExpression} to validate by validating its encapsulated expression
     * @return A number indicating the validation result. {@link #isValid(int, int)} can be used to
     * determine the validation status of an expression based on its position
     */
    protected int validateSubstringExpression(SubstringExpression expression) {

        int result = 0;

        // Validate the first expression
        if (expression.hasFirstExpression()) {
            Expression firstExpression = expression.getFirstExpression();

            // Special case for state field path expression, association field is not allowed
            StateFieldPathExpression pathExpression = getStateFieldPathExpression(firstExpression);

            if (pathExpression != null) {
                boolean valid = validateStateFieldPathExpression(pathExpression, PathType.BASIC_FIELD_ONLY);
                updateStatus(result, 0, valid);
            }
            else {
                firstExpression.accept(this);
            }
        }

        // Validate the second expression
        expression.getSecondExpression().accept(this);

        // Validate the third expression
        expression.getThirdExpression().accept(this);

        return result;
    }

    /**
     * Validates the encapsulated expression of the given subtraction expression. The test to perform is:
     * <ul>
     * <li>If the left or right expression is a path expression, validation makes sure it is a basic
     * mapping, an association field is not allowed.</li>
     * <li>If the left or right expression is not a path expression, validation will be redirected to
     * that expression but the returned status will not be updated.</li>
     * </ul>
     *
     * @param expression The {@link SubtractionExpression} to validate by validating its encapsulated
     * expression
     * @return A number indicating the validation result. {@link #isValid(int, int)} can be used to
     * determine the validation status of an expression based on its position
     */
    protected int validateSubtractionExpression(SubtractionExpression expression) {
        return validateArithmeticExpression(
            expression,
            SubtractionExpression_LeftExpression_WrongType,
            SubtractionExpression_RightExpression_WrongType
        );
    }

    /**
     * Validates the encapsulated expression of the given <code><b>MOD</b></code> expression. The
     * test to perform is:
     * <ul>
     * <li>If the encapsulated expression is a path expression, validation makes sure it is a basic
     * mapping, an association field is not allowed.</li>
     * <li>If the encapsulated expression is not a path expression, validation will be redirected to
     * that expression but the returned status will not be changed.</li>
     * </ul>
     *
     * @param expression The {@link ModExpression} to validate by validating its encapsulated expression
     * @return <code>false</code> if the encapsulated expression was validated and is invalid;
     * <code>true</code> otherwise
     */
    protected boolean validateSumFunction(SumFunction expression) {
        return validateFunctionPathExpression(expression);
    }

    /**
     * Validates the given {@link StateFieldPathExpression}, which means the path does not represent
     * a mapping, or an enum constant.
     *
     * @param expression The {@link StateFieldPathExpression} the validate
     * @return <code>Boolean.TRUE</code> or <code>Boolean.FALSE</code> if the given {@link
     * StateFieldPathExpression} was validated by this method; <code>null</code> if it could not be
     * validated (as being valid or invalid)
     */
    protected Boolean validateThirdPartyStateFieldPathExpression(StateFieldPathExpression expression) {
        return null;
    }

    /**
     * Validates the given {@link TreatExpression}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link TreatExpression} to validate
     */
    protected void validateTreatExpression(TreatExpression expression) {
        super.visit(expression);
    }

    /**
     * Validates the encapsulated expression of the given <code><b>TRIM</b></code> expression. The
     * test to perform is:
     * <ul>
     * <li>If the encapsulated expression is a path expression, validation makes sure it is a basic
     * mapping, an association field is not allowed.</li>
     * <li>If the encapsulated expression is not a path expression, validation will be redirected to
     * that expression but the returned status will not be changed.</li>
     * </ul>
     *
     * @param expression The {@link TrimExpression} to validate by validating its encapsulated expression
     * @return <code>false</code> if the encapsulated expression was validated and is invalid;
     * <code>true</code> otherwise
     */
    protected boolean validateTrimExpression(TrimExpression expression) {
        return validateFunctionPathExpression(expression);
    }

    /**
     * Validates the given {@link TypeExpression}. The test to perform is:
     * <ul>
     *    <li>If the encapsulated expression is a path expression, validation makes sure it is an
     *        association field, a basic field is not allowed.</li>
     * </ul>
     *
     * @param expression The {@link TypeExpression} to validate
     * @return <code>false</code> if the encapsulated expression was validated and is invalid;
     * <code>true</code> otherwise
     */
    protected boolean validateTypeExpression(TypeExpression expression) {

        // Validate the expression
        if (expression.hasEncapsulatedExpression()) {
            Expression encapsulatedExpression = expression.getExpression();

            // Special case for state field path expression, only association field is allowed
            StateFieldPathExpression pathExpression = getStateFieldPathExpression(encapsulatedExpression);

            if (pathExpression != null) {
                return validateStateFieldPathExpression(pathExpression, PathType.ASSOCIATION_FIELD_ONLY);
            }
            else {
                encapsulatedExpression.accept(this);
            }
        }

        return true;
    }

    /**
     * Validates the given {@link UpdateClause}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link UpdateClause} to validate
     */
    protected void validateUpdateClause(UpdateClause expression) {
        super.visit(expression);
    }

    /**
     * Validates the given {@link UpdateItem} by validating the traversability of the path
     * expression. The path expression is valid if it follows one of the following rules:
     * <ul>
     * <li>The identification variable is omitted if it's not defined in the <b>FROM</b> clause;
     * <li>The last path is a state field;
     * <li>Only embedded field can be traversed.
     * </ul>
     *
     * @param expression {@link UpdateItem} to validate its path expression
     * @return <code>true</code> if the path expression is valid; <code>false</code> otherwise
     */
    protected boolean validateUpdateItem(UpdateItem expression) {

        boolean valid = true;

        if (expression.hasStateFieldPathExpression()) {

            // Retrieve the state field path expression
            StateFieldPathExpression pathExpression = getStateFieldPathExpression(expression.getStateFieldPathExpression());

            if ((pathExpression != null) &&
                (pathExpression.hasIdentificationVariable() ||
                 pathExpression.hasVirtualIdentificationVariable())) {

                // Start traversing the path expression by first retrieving the managed type
                Object managedType = helper.getManagedType(pathExpression.getIdentificationVariable());

                if (managedType != null) {

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

                        // Retrieve the mapping
                        String path = pathExpression.getPath(index);
                        Object mapping = helper.getMappingNamed(managedType, path);

                        // Not resolvable
                        if (mapping == null) {
                            addProblem(pathExpression, UpdateItem_NotResolvable, pathExpression.toParsedText());
                            valid = false;
                            break;
                        }
                        // A collection mapping cannot be traversed or a value cannot be assigned to it
                        else if (helper.isCollectionMapping(mapping)) {
                            addProblem(pathExpression, UpdateItem_RelationshipPathExpression);
                            valid = false;
                            break;
                        }
                        // Validate an intermediate path (n + 1, ..., n - 2)
                        else if (index + 1 < count) {

                            // A relationship mapping cannot be traversed
                            if (helper.isRelationshipMapping(mapping)) {
                                addProblem(pathExpression, UpdateItem_RelationshipPathExpression);
                                valid = false;
                                break;
                            }
                            // A basic mapping cannot be traversed
                            else if (helper.isPropertyMapping(mapping)) {
                                addProblem(pathExpression, UpdateItem_RelationshipPathExpression);
                                valid = false;
                                break;
                            }
                            // Retrieve the embeddable mapping's reference managed type
                            else {
                                managedType = helper.getReferenceManagedType(mapping);

                                if (managedType == null) {
                                    addProblem(pathExpression, UpdateItem_NotResolvable, pathExpression.toParsedText());
                                    valid = false;
                                    break;
                                }
                            }
                        }
                    }
                }
                else {
                    addProblem(pathExpression, UpdateItem_NotResolvable, pathExpression.toParsedText());
                    valid = false;
                }
            }
            else {
                addProblem(pathExpression, UpdateItem_NotResolvable, expression.getStateFieldPathExpression().toParsedText());
                valid = false;
            }
        }

        return valid;
    }

    /**
     * Validates the given {@link UpdateStatement}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link UpdateStatement} to validate
     */
    protected void validateUpdateStatement(UpdateStatement expression) {
        super.visit(expression);
    }

    /**
     * Validates the encapsulated expression of the given <code><b>UPPER</b></code> expression. The
     * test to perform is:
     * <ul>
     * <li>If the encapsulated expression is a path expression, validation makes sure it is a basic
     * mapping, an association field is not allowed.</li>
     * <li>If the encapsulated expression is not a path expression, validation will be redirected to
     * that expression but the returned status will not be changed.</li>
     * </ul>
     *
     * @param expression The {@link UpperExpression} to validate by validating its encapsulated expression
     * @return <code>false</code> if the encapsulated expression was validated and is invalid;
     * <code>true</code> otherwise
     */
    protected boolean validateUpperExpression(UpperExpression expression) {
        return validateFunctionPathExpression(expression);
    }

    /**
     * Validates the given {@link ValueExpression}. The default behavior does not require to
     * semantically validate it.
     *
     * @param expression The {@link ValueExpression} to validate
     */
    protected void validateValueExpression(ValueExpression expression) {
        super.visit(expression);
    }

    /**
     * Validates the given {@link WhenClause}. The default behavior does not require to semantically
     * validate it.
     *
     * @param expression The {@link WhenClause} to validate
     */
    protected void validateWhenClause(WhenClause expression) {
        super.visit(expression);
    }

    /**
     * Validates the given {@link WhereClause}. The default behavior does not require to semantically
     * validate it.
     *
     * @param expression The {@link WhereClause} to validate
     */
    protected void validateWhereClause(WhereClause expression) {
        super.visit(expression);
    }

    /**
     * Returns the type of path expression that is valid for a count function; which is the left
     * expression in a <code><b>COUNT</b></code> expression.
     *
     * @return By default, any field are allowed except collection
     */
    protected PathType validPathExpressionTypeForCountFunction() {
        return PathType.ANY_FIELD;
    }

    /**
     * Returns the type of path expression that is valid for the expression being tested by an
     * <code><b>IN</b></code> expression; which is the left expression.
     *
     * @return By default, any field (without collection) is allowed
     */
    protected PathType validPathExpressionTypeForInExpression() {
        return PathType.ANY_FIELD;
    }

    /**
     * Returns the type of path expression that is valid for an <code>IN</code> items; which is the
     * left expression in a <code><b>IN</b></code> expression.
     *
     * @return By default, any field are allowed except collection
     */
    protected PathType validPathExpressionTypeForInItem() {
        return PathType.ANY_FIELD;
    }

    /**
     * Returns the type of path expression that is valid for a string expression; which is the left
     * expression in a <code><b>LIKE</b></code> expression.
     *
     * @return By default, only basic field are allowed
     */
    protected PathType validPathExpressionTypeForStringExpression() {
        return PathType.BASIC_FIELD_ONLY;
    }

    @Override
    public final void visit(AbsExpression expression) {
        validateAbsExpression(expression);
    }

    @Override
    public final void visit(AbstractSchemaName expression) {
        validateAbstractSchemaName(expression);
    }

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

    @Override
    public final void visit(AllOrAnyExpression expression) {
        validateAllOrAnyExpression(expression);
    }

    @Override
    public final void visit(AndExpression expression) {
        validateAndExpression(expression);
    }

    @Override
    public final void visit(ArithmeticFactor expression) {
        validateArithmeticExpression(expression);
    }

    @Override
    public final void visit(AvgFunction expression) {
        validateAvgFunction(expression);
    }

    @Override
    public final void visit(BadExpression expression) {
        // Nothing to validate semantically
    }

    @Override
    public final void visit(BetweenExpression expression) {
        validateBetweenExpression(expression);
    }

    @Override
    public final void visit(CaseExpression expression) {
        validateCaseExpression(expression);
    }

    @Override
    public final void visit(CoalesceExpression expression) {
        validateCoalesceExpression(expression);
    }

    @Override
    public final void visit(CollectionExpression expression) {
        // Nothing to validate semantically
        super.visit(expression);
    }

    @Override
    public final void visit(CollectionMemberDeclaration expression) {
        validateCollectionMemberDeclaration(expression);
    }

    @Override
    public final void visit(CollectionMemberExpression expression) {
        validateCollectionMemberExpression(expression);
    }

    @Override
    public final void visit(CollectionValuedPathExpression expression) {
        // Validated by the parent of the expression
    }

    @Override
    public final void visit(ComparisonExpression expression) {
        validateComparisonExpression(expression);
    }

    @Override
    public final void visit(ConcatExpression expression) {
        validateConcatExpression(expression);
    }

    @Override
    public final void visit(ConstructorExpression expression) {
        validateConstructorExpression(expression);
    }

    @Override
    public final void visit(CountFunction expression) {
        validateCountFunction(expression);
    }

    @Override
    public final void visit(DateTime expression) {
        validateDateTime(expression);
    }

    @Override
    public final void visit(DeleteClause expression) {
        validateDeleteClause(expression);
    }

    @Override
    public final void visit(DeleteStatement expression) {
        validateDeleteStatement(expression);
    }

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

    @Override
    public final void visit(EmptyCollectionComparisonExpression expression) {
        validateCollectionValuedPathExpression(expression.getExpression(), true);
    }

    @Override
    public final void visit(EntityTypeLiteral expression) {
        validateEntityTypeLiteral(expression);
    }

    @Override
    public final void visit(EntryExpression expression) {
        validateEntryExpression(expression);
    }

    @Override
    public final void visit(ExistsExpression expression) {
        validateExistsExpression(expression);
    }

    @Override
    public final void visit(FromClause expression) {
        validateFromClause(expression);
    }

    @Override
    public final void visit(FunctionExpression expression) {
        validateFunctionExpression(expression);
    }

    @Override
    public final void visit(GroupByClause expression) {
        validateGroupByClause(expression);
    }

    @Override
    public final void visit(HavingClause expression) {
        validateHavingClause(expression);
    }

    @Override
    public final void visit(IdentificationVariable expression) {
        validateIdentificationVariable(expression);
    }

    @Override
    public final void visit(IdentificationVariableDeclaration expression) {
        validateIdentificationVariableDeclaration(expression);
    }

    @Override
    public final void visit(IndexExpression expression) {
        validateIndexExpression(expression);
    }

    @Override
    public final void visit(InExpression expression) {
        validateInExpression(expression);
    }

    @Override
    public final void visit(InputParameter expression) {
        // Nothing to validate semantically
    }

    @Override
    public final void visit(Join expression) {
        validateJoin(expression);
    }

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

    @Override
    public final void visit(KeyExpression expression) {
        validateKeyExpression(expression);
    }

    @Override
    public final void visit(KeywordExpression expression) {
        // Nothing semantically to validate
    }

    @Override
    public final void visit(LengthExpression expression) {
        validateLengthExpression(expression);
    }

    @Override
    public final void visit(LikeExpression expression) {
        validateLikeExpression(expression);
    }

    @Override
    public final void visit(LocateExpression expression) {
        validateLocateExpression(expression);
    }

    @Override
    public final void visit(LowerExpression expression) {
        validateLowerExpression(expression);
    }

    @Override
    public final void visit(MaxFunction expression) {
        validateMaxFunction(expression);
    }

    @Override
    public final void visit(MinFunction expression) {
        validateMinFunction(expression);
    }

    @Override
    public final void visit(ModExpression expression) {
        validateModExpression(expression);
    }

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

    @Override
    public final void visit(NotExpression expression) {
        validateNotExpression(expression);
    }

    @Override
    public final void visit(NullComparisonExpression expression) {
        validateNullComparisonExpression(expression);
    }

    @Override
    public final void visit(NullExpression expression) {
        // Nothing semantically to validate
    }

    @Override
    public final void visit(NullIfExpression expression) {
        validateNullIfExpression(expression);
    }

    @Override
    public final void visit(NumericLiteral expression) {
        // Nothing semantically to validate
    }

    @Override
    public final void visit(ObjectExpression expression) {
        validateObjectExpression(expression);
    }

    @Override
    public final void visit(OnClause expression) {
        validateOnClause(expression);
    }

    @Override
    public final void visit(OrderByClause expression) {
        validateOrderByClause(expression);
    }

    @Override
    public final void visit(OrderByItem expression) {
        validateOrderByItem(expression);
    }

    @Override
    public final void visit(OrExpression expression) {
        validateOrExpression(expression);
    }

    @Override
    public final void visit(RangeVariableDeclaration expression) {
        validateRangeVariableDeclaration(expression);
    }

    @Override
    public final void visit(ResultVariable expression) {

        try {
            registerIdentificationVariable = false;
            validateResultVariable(expression);
        }
        finally {
            registerIdentificationVariable = true;
        }
    }

    @Override
    public final void visit(SelectClause expression) {
        validateSelectClause(expression);
    }

    @Override
    public final void visit(SelectStatement expression) {
        validateSelectStatement(expression);
    }

    @Override
    public final void visit(SimpleFromClause expression) {
        validateSimpleFromClause(expression);
    }

    @Override
    public final void visit(SimpleSelectClause expression) {
        validateSimpleSelectClause(expression);
    }

    @Override
    public final void visit(SimpleSelectStatement expression) {
        validateSimpleSelectStatement(expression);
    }

    @Override
    public final void visit(SizeExpression expression) {
        validateSizeExpression(expression);
    }

    @Override
    public final void visit(SqrtExpression expression) {
        validateSqrtExpression(expression);
    }

    @Override
    public final void visit(StateFieldPathExpression expression) {
        validateStateFieldPathExpression(expression, PathType.ANY_FIELD);
    }

    @Override
    public final void visit(StringLiteral expression) {
        // Nothing semantically to validate
    }

    @Override
    public final void visit(SubExpression expression) {
        // Nothing semantically to validate
        super.visit(expression);
    }

    @Override
    public final void visit(SubstringExpression expression) {
        validateSubstringExpression(expression);
    }

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

    @Override
    public final void visit(SumFunction expression) {
        validateSumFunction(expression);
    }

    @Override
    public final void visit(TreatExpression expression) {
        validateTreatExpression(expression);
    }

    @Override
    public final void visit(TrimExpression expression) {
        validateTrimExpression(expression);
    }

    @Override
    public final void visit(TypeExpression expression) {
        validateTypeExpression(expression);
    }

    @Override
    public final void visit(UnknownExpression expression) {
        // Nothing semantically to validate
    }

    @Override
    public final void visit(UpdateClause expression) {
        validateUpdateClause(expression);
    }

    @Override
    public final void visit(UpdateItem expression) {
         validateUpdateItem(expression);
    }

    @Override
    public final void visit(UpdateStatement expression) {
        validateUpdateStatement(expression);
    }

    @Override
    public final void visit(UpperExpression expression) {
        validateUpperExpression(expression);
    }

    @Override
    public final void visit(ValueExpression expression) {
        validateValueExpression(expression);
    }

    @Override
    public final void visit(WhenClause expression) {
        validateWhenClause(expression);
    }

    @Override
    public final void visit(WhereClause expression) {
        validateWhereClause(expression);
    }

    // Made static final for performance reasons.
    /**
     * This visitor is meant to retrieve an {@link CollectionValuedPathExpression} if the visited
     * {@link Expression} is that object.
     */
    protected static final class CollectionValuedPathExpressionVisitor extends AbstractExpressionVisitor {

        /**
         * The {@link CollectionValuedPathExpression} that was visited; <code>null</code> if he was not.
         */
        protected CollectionValuedPathExpression expression;

        /**
         * Default constructor.
         */
        protected CollectionValuedPathExpressionVisitor() {
        }

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

    // Made static final for performance reasons.
    protected static final class ComparingEntityTypeLiteralVisitor extends AbstractExpressionVisitor {

        protected IdentificationVariable expression;
        public boolean result;

        /**
         * Default constructor.
         */
        protected ComparingEntityTypeLiteralVisitor() {
        }

        @Override
        public void visit(ComparisonExpression expression) {
            result = true;
        }

        @Override
        public void visit(IdentificationVariable expression) {
            if (this.expression == expression) {
                expression.getParent().accept(this);
            }
        }

        @Override
        public void visit(SubExpression expression) {
            // Make sure to bypass any sub expression
            expression.getParent().accept(this);
        }
    }

    // Made static final for performance reasons.
    /**
     * This visitor compares the left and right expressions of a comparison expression and gathers
     * information about those expressions if they are an identification variable or a path expression.
     */
    protected static final class ComparisonExpressionVisitor extends AnonymousExpressionVisitor {

        private final AbstractSemanticValidator validator;
        public boolean leftIdentificationVariable;
        public boolean leftIdentificationVariableValid;
        public boolean leftStateFieldPathExpression;
        public boolean leftStateFieldPathExpressionValid;
        public boolean rightIdentificationVariable;
        public boolean rightIdentificationVariableValid;
        public boolean rightStateFieldPathExpression;
        public boolean rightStateFieldPathExpressionValid;
        public boolean validatingLeftExpression;

        private ComparisonExpressionVisitor(AbstractSemanticValidator validator) {
            this.validator = validator;
        }

        /**
         * Resets the flags.
         */
        private void dispose() {
            leftIdentificationVariable         = false;
            leftIdentificationVariableValid    = false;
            leftStateFieldPathExpression       = false;
            leftStateFieldPathExpressionValid  = false;
            rightIdentificationVariable        = false;
            rightIdentificationVariableValid   = false;
            rightStateFieldPathExpression      = false;
            rightStateFieldPathExpressionValid = false;
        }

        @Override
        protected void visit(Expression expression) {
            // Redirect to the validator, nothing special is required
            expression.accept(validator);
        }

        @Override
        public void visit(IdentificationVariable expression) {

            // Make sure the identification variable is not a result variable
            if (!validator.helper.isResultVariable(expression.getVariableName())) {

                if (validatingLeftExpression) {
                    leftIdentificationVariable = !expression.isVirtual();

                    // Make sure what was parsed is a valid identification variable
                    leftIdentificationVariableValid = validator.validateIdentificationVariable(expression);
                }
                else {
                    rightIdentificationVariable = !expression.isVirtual();

                    // Make sure what was parsed is a valid identification variable
                    rightIdentificationVariableValid = validator.validateIdentificationVariable(expression);
                }
            }
        }

        @Override
        public void visit(StateFieldPathExpression expression) {

            if (validatingLeftExpression) {
                leftStateFieldPathExpression = true;

                // Make sure what was parsed is a valid path expression
                leftStateFieldPathExpressionValid = validator.validateStateFieldPathExpression(
                    expression,
                    PathType.ANY_FIELD_INCLUDING_COLLECTION
                );
            }
            else {
                rightStateFieldPathExpression = true;

                // Make sure what was parsed is a valid path expression
                rightStateFieldPathExpressionValid = validator.validateStateFieldPathExpression(
                    expression,
                    PathType.ANY_FIELD_INCLUDING_COLLECTION
                );
            }
        }
    }

    // Made static for performance reasons.
    protected static class FirstDeclarationVisitor extends AnonymousExpressionVisitor {

        protected boolean valid;

        /**
         * Default constructor.
         */
        protected FirstDeclarationVisitor() {
        }

        @Override
        public void visit(AbstractSchemaName expression) {
            valid = true;
        }

        @Override
        public void visit(BadExpression expression) {
            // Already validated, no need to duplicate the issue
            valid = false;
        }

        @Override
        protected void visit(Expression expression) {
            valid = false;
        }

        @Override
        public void visit(IdentificationVariableDeclaration expression) {
            expression.getRangeVariableDeclaration().accept(this);
        }

        @Override
        public void visit(NullExpression expression) {
            // Already validated, no need to duplicate the issue
            valid = false;
        }

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

    // Made static final for performance reasons.
    protected static final class InItemsVisitor extends AnonymousExpressionVisitor {

        private final AbstractSemanticValidator validator;

        protected InItemsVisitor(AbstractSemanticValidator validator) {
            this.validator = validator;
        }

        @Override
        protected void visit(Expression expression) {
            expression.accept(validator);
        }

        @Override
        public void visit(StateFieldPathExpression expression) {
            validator.validateStateFieldPathExpression(expression, validator.validPathExpressionTypeForInItem());
        }
    }

    // Made static for performance reasons.
    /**
     * This enumeration allows {@link AbstractSemanticValidator#validateStateFieldPathExpression(
     * StateFieldPathExpression, PathType)} to validate the type of the mapping and to make sure it
     * is allowed based on its location.
     */
    protected static enum PathType {

        /**
         * This will allow basic, and association fields to be specified.
         */
        ANY_FIELD,

        /**
         * This will allow basic, and association fields to be specified.
         */
        ANY_FIELD_INCLUDING_COLLECTION,

        /**
         * This will allow association fields to be specified but basic mappings are not valid.
         */
        ASSOCIATION_FIELD_ONLY,

        /**
         * This will allow basic fields to be specified but association mappings are not valid.
         */
        BASIC_FIELD_ONLY
    }

    // Made static final for performance reasons.
    /**
     * This visitor is meant to retrieve an {@link StateFieldPathExpressionVisitor} if the visited
     * {@link Expression} is that object.
     */
    protected static final class StateFieldPathExpressionVisitor extends AbstractExpressionVisitor {

        /**
         * The {@link StateFieldPathExpression} that was visited; <code>null</code> if it was not.
         */
        protected StateFieldPathExpression expression;

        /**
         * Default constructor.
         */
        protected StateFieldPathExpressionVisitor() {
        }

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

    // Made static final for performance reasons.
    protected static final class SubqueryFirstDeclarationVisitor extends FirstDeclarationVisitor {

        /**
         * Default constructor.
         */
        protected SubqueryFirstDeclarationVisitor() {
        }

        @Override
        public void visit(CollectionValuedPathExpression expression) {
            valid = true;
        }
    }

    // Made static for performance reasons.
    protected static class TopLevelFirstDeclarationVisitor extends FirstDeclarationVisitor {

        /**
         * Default constructor.
         */
        protected TopLevelFirstDeclarationVisitor() {
        }

        @Override
        public void visit(AbstractSchemaName expression) {
            // TODO
            valid = true;
        }
    }
}
