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

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

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Stack;
import org.eclipse.persistence.jpa.jpql.AbstractValidator.JPQLQueryBNFValidator;
import org.eclipse.persistence.jpa.jpql.Assert;
import org.eclipse.persistence.jpa.jpql.ExpressionTools;
import org.eclipse.persistence.jpa.jpql.JPAVersion;
import org.eclipse.persistence.jpa.jpql.JPQLQueryDeclaration.Type;
import org.eclipse.persistence.jpa.jpql.LiteralType;
import org.eclipse.persistence.jpa.jpql.WordParser;
import org.eclipse.persistence.jpa.jpql.parser.AbsExpression;
import org.eclipse.persistence.jpa.jpql.parser.AbstractConditionalClause;
import org.eclipse.persistence.jpa.jpql.parser.AbstractDoubleEncapsulatedExpression;
import org.eclipse.persistence.jpa.jpql.parser.AbstractExpressionVisitor;
import org.eclipse.persistence.jpa.jpql.parser.AbstractFromClause;
import org.eclipse.persistence.jpa.jpql.parser.AbstractOrderByClause;
import org.eclipse.persistence.jpa.jpql.parser.AbstractPathExpression;
import org.eclipse.persistence.jpa.jpql.parser.AbstractSchemaName;
import org.eclipse.persistence.jpa.jpql.parser.AbstractSelectClause;
import org.eclipse.persistence.jpa.jpql.parser.AbstractSelectStatement;
import org.eclipse.persistence.jpa.jpql.parser.AbstractSingleEncapsulatedExpression;
import org.eclipse.persistence.jpa.jpql.parser.AbstractTraverseParentVisitor;
import org.eclipse.persistence.jpa.jpql.parser.AbstractTripleEncapsulatedExpression;
import org.eclipse.persistence.jpa.jpql.parser.AdditionExpression;
import org.eclipse.persistence.jpa.jpql.parser.AggregateFunction;
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.ArithmeticExpressionFactory;
import org.eclipse.persistence.jpa.jpql.parser.ArithmeticFactor;
import org.eclipse.persistence.jpa.jpql.parser.ArithmeticPrimaryBNF;
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.CaseOperandBNF;
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.CollectionValuedPathExpressionBNF;
import org.eclipse.persistence.jpa.jpql.parser.ComparisonExpression;
import org.eclipse.persistence.jpa.jpql.parser.ComparisonExpressionFactory;
import org.eclipse.persistence.jpa.jpql.parser.CompoundExpression;
import org.eclipse.persistence.jpa.jpql.parser.ConcatExpression;
import org.eclipse.persistence.jpa.jpql.parser.ConditionalExpressionBNF;
import org.eclipse.persistence.jpa.jpql.parser.ConstructorExpression;
import org.eclipse.persistence.jpa.jpql.parser.ConstructorItemBNF;
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.ExpressionFactory;
import org.eclipse.persistence.jpa.jpql.parser.ExpressionVisitor;
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.GroupByItemBNF;
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.IdentifierRole;
import org.eclipse.persistence.jpa.jpql.parser.InExpression;
import org.eclipse.persistence.jpa.jpql.parser.InExpressionItemBNF;
import org.eclipse.persistence.jpa.jpql.parser.IndexExpression;
import org.eclipse.persistence.jpa.jpql.parser.InputParameter;
import org.eclipse.persistence.jpa.jpql.parser.InternalBetweenExpressionBNF;
import org.eclipse.persistence.jpa.jpql.parser.InternalJoinBNF;
import org.eclipse.persistence.jpa.jpql.parser.JPQLExpression;
import org.eclipse.persistence.jpa.jpql.parser.JPQLGrammar;
import org.eclipse.persistence.jpa.jpql.parser.JPQLQueryBNF;
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.LogicalExpression;
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.NewValueBNF;
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.OrderByItem.Ordering;
import org.eclipse.persistence.jpa.jpql.parser.OrderByItemBNF;
import org.eclipse.persistence.jpa.jpql.parser.QueryPosition;
import org.eclipse.persistence.jpa.jpql.parser.RangeVariableDeclaration;
import org.eclipse.persistence.jpa.jpql.parser.RangeVariableDeclarationBNF;
import org.eclipse.persistence.jpa.jpql.parser.ResultVariable;
import org.eclipse.persistence.jpa.jpql.parser.ScalarExpressionBNF;
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.StringPrimaryBNF;
import org.eclipse.persistence.jpa.jpql.parser.SubExpression;
import org.eclipse.persistence.jpa.jpql.parser.SubqueryBNF;
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 org.eclipse.persistence.jpa.jpql.tools.ContentAssistProposals.ClassType;
import org.eclipse.persistence.jpa.jpql.tools.resolver.Declaration;
import org.eclipse.persistence.jpa.jpql.tools.resolver.Resolver;
import org.eclipse.persistence.jpa.jpql.tools.resolver.StateFieldResolver;
import org.eclipse.persistence.jpa.jpql.tools.spi.IEntity;
import org.eclipse.persistence.jpa.jpql.tools.spi.IManagedType;
import org.eclipse.persistence.jpa.jpql.tools.spi.IMapping;
import org.eclipse.persistence.jpa.jpql.tools.spi.IType;
import org.eclipse.persistence.jpa.jpql.tools.utility.filter.AndFilter;
import org.eclipse.persistence.jpa.jpql.utility.CollectionTools;
import org.eclipse.persistence.jpa.jpql.utility.filter.Filter;
import org.eclipse.persistence.jpa.jpql.utility.filter.NullFilter;
import static org.eclipse.persistence.jpa.jpql.parser.AbstractExpression.*;

/**
 * The visitor provides support for finding the possible proposals within a JPQL query at a certain
 * position.
 * <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.
 *
 * @version 2.5
 * @since 2.4
 * @author Pascal Filion
 */
@SuppressWarnings({"nls", "unused"}) // unused used for the import statement: see bug 330740
public abstract class AbstractContentAssistVisitor extends AnonymousExpressionVisitor {

    /**
     * This is used to change the position of the cursor in order to add possible proposals
     */
    protected Stack<Integer> corrections;

    /**
     * The cached helpers that are used by this visitor to add valid content assist proposals.
     */
    protected Map<Class<?>, Object> helpers;

    /**
     * This map contains the {@link Filter} that is used to determine when an identifier is a valid
     * proposal, some of them depends on the expression's type.
     */
    protected Map<String, Filter<Expression>> identifierFilters;

    /**
     * Used to prevent and infinite recursion when one of the visit method is virtually asking a
     * child expression to be visited.
     */
    protected Stack<Expression> lockedExpressions;

    /**
     * The set of possible proposals gathered based on the position in the query.
     */
    protected DefaultContentAssistProposals proposals;

    /**
     * The context used to query information about the JPQL query.
     */
    protected final JPQLQueryContext queryContext;

    /**
     * Contains the position of the cursor within the parsed {@link Expression} from the root node
     * up to the deepest leaf node.
     */
    protected QueryPosition queryPosition;

    /**
     * A virtual space is used to move the position of the cursor by adding an extra space in order
     * to find some proposals within an expression. This is usually used when the trailing whitespace
     * is not owned by the child expression but by one of its parents.
     */
    protected Stack<Integer> virtualSpaces;

    /**
     * The current word, which was retrieved from the JPQL query based on the position of the cursor.
     * The word is the partial string found to the left of the cursor and up to the cursor.
     */
    protected String word;

    /**
     * This is used to retrieve words from the actual JPQL query.
     */
    protected WordParser wordParser;

    /**
     * This {@link Filter} is used to say the {@link Expression} is invalid without doing anything.
     */
    protected static final Filter<Expression> INVALID_IDENTIFIER_FILTER = new Filter<Expression>() {
        @Override
        public boolean accept(Expression expression) {
            return false;
        }
    };

    /**
     * A constant for the length of a whitespace, which is 1.
     */
    protected static final int SPACE_LENGTH = 1;

    /**
     * This {@link Filter} is used to say the {@link Expression} is valid without doing anything.
     */
    protected static final Filter<Expression> VALID_IDENTIFIER_FILTER = new Filter<Expression>() {
        @Override
        public boolean accept(Expression expression) {
            return true;
        }
    };

    /**
     * Creates a new <code>AbstractContentAssistVisitor</code>.
     *
     * @param queryContext The context used to query information about the JPQL query
     * @exception NullPointerException The {@link JPQLQueryContext} cannot be <code>null</code>
     */
    protected AbstractContentAssistVisitor(JPQLQueryContext queryContext) {
        super();
        Assert.isNotNull(queryContext, "The JPQLQueryContext cannot be null");
        this.queryContext = queryContext;
        initialize();
    }

    /**
     * Adds the given JPQL identifier as a valid proposal if its role is {@link IdentifierRole#AGGREGATE}
     * and the beginning starts with the current word.
     *
     * @param identifier The JPQL identifier to add as a valid proposal if it passes the checks
     */
    protected void addAggregateIdentifier(String identifier) {
        if (isAggregate(identifier)) {
            addIdentifier(identifier);
        }
    }

    /**
     * Adds the JPQL identifiers that are registered with the given {@link JPQLQueryBNF} as valid
     * proposals if their role is {@link IdentifierRole#AGGREGATE} and the beginning starts with the
     * current word.
     *
     * @param queryBNF The {@link JPQLQueryBNF} for which the registered JPQL identifiers will be
     * added as proposals if they pass the checks
     */
    protected void addAggregateIdentifiers(JPQLQueryBNF queryBNF) {
        for (String identifier : queryBNF.getIdentifiers()) {
            addAggregateIdentifier(identifier);
        }
    }

    /**
     * Adds the JPQL identifiers that are registered with the given {@link JPQLQueryBNF} as valid
     * proposals if their role is {@link IdentifierRole#AGGREGATE} and the beginning starts with the
     * current word.
     *
     * @param queryBNFId The unique of the {@link JPQLQueryBNF} for which the registered JPQL
     * identifiers will be added as proposals if they pass the checks
     */
    protected void addAggregateIdentifiers(String queryBNFId) {
        addAggregateIdentifiers(getQueryBNF(queryBNFId));
    }

    /**
     * Adds the JPQL identifiers which correspond to the arithmetic operators as valid proposals. The
     * word has to be an empty string.
     */
    protected void addArithmeticIdentifiers() {
        if (word.length() == 0) {
            addExpressionFactoryIdentifiers(ArithmeticExpressionFactory.ID);
        }
    }

    /**
     * Adds the given JPQL identifier as a valid proposal if its role is {@link IdentifierRole#CLAUSE}
     * and the beginning starts with the current word.
     *
     * @param identifier The JPQL identifier to add as a valid proposal if it passes the checks
     */
    protected void addClauseIdentifier(String identifier) {
        if (isClause(identifier)) {
            addIdentifier(identifier);
        }
    }

    /**
     * Adds the JPQL identifiers that are registered with the given {@link JPQLQueryBNF} as valid
     * proposals if their role is {@link IdentifierRole#CLAUSE} and the beginning starts with the
     * current word.
     *
     * @param queryBNF The {@link JPQLQueryBNF} for which the registered JPQL identifiers will be
     * added as proposals if they pass the checks
     */
    protected void addClauseIdentifiers(JPQLQueryBNF queryBNF) {
        for (String identifier : queryBNF.getIdentifiers()) {
            addClauseIdentifier(identifier);
        }
    }

    /**
     * Adds the JPQL identifiers that are registered with the given {@link JPQLQueryBNF} as valid
     * proposals if their role is {@link IdentifierRole#CLAUSE} and the beginning starts with the
     * current word.
     *
     * @param queryBNFId The unique identifier of the {@link JPQLQueryBNF} for which the registered
     * JPQL identifiers will be
     * added as proposals if they pass the checks
     */
    protected void addClauseIdentifiers(String queryBNFId) {
        addClauseIdentifiers(getQueryBNF(queryBNFId));
    }

    /**
     * Adds the JPQL identifiers which correspond to the comparison operators as valid proposals. The
     * word has to be an empty string.
     *
     * @param expression The {@link Expression} is preceding the position of the cursor and will help
     * to determine which of the comparison operators are valid
     */
    protected void addComparisonIdentifiers(Expression expression) {

        if (word.length() == 0) {

            for (String identifier : getExpressionFactory(ComparisonExpressionFactory.ID).identifiers()) {
                Filter<Expression> filter = getFilter(identifier);
                if (filter.accept(expression)) {
                    addIdentifier(identifier);
                }
            }
        }
    }

    /**
     * Adds the composite JPQL identifier by following the given rules:
     *
     * <ul>
     * <li>If the word is empty and the offset is -1, then use the rule used by {@link
     * #addIdentifier(String)};</li>
     * <li>Otherwise checks the ending of the JPQL query with a portion of the identifier from the
     * entire length of the identifier to the given offset by cutting off the trailing characters.</li>
     * </ul>
     *
     * @param identifier The composite JPQL identifier to add as valid proposal. The composite part
     * means it is an identifier composed of more than one word, example: <code><b>GROUP BY</b></code>
     * @param offset The smallest length of the given identifier to test against the ending of the
     * JPQL query based on the position of the cursor. The offset is exclusive
     */
    protected void addCompositeIdentifier(String identifier, int offset) {

        // No need to check by fragmenting the composite identifier
        if ((word.length() == 0) && (offset == -1)) {
            addIdentifier(identifier);
        }
        else if (isValidVersion(identifier)) {

            // Make sure the offset is not -1
            offset = Math.max(offset, 0);

            // Cut the composite identifier by removing the ending portion one character at a time
            // and see if the JPQL query is ending with that same text
            // Example: "SELECT e FROM Employee e ORDER B" and the JPQL identifier is "ORDER BY", the
            //          test will do "ORDER B", "ORDER ", "ORDER", "ORD", "OR", "O" and if it does
            //          match then we have to make sure there is a whitespace before to make sure it's
            //          a complete word
            int position = queryPosition.getPosition();

            for (int index = identifier.length(); --index > offset; ) {
                String fragment = identifier.substring(0, index);

                // The text ends with the beginning portion of the JPQL identifier,
                // make sure it has a whitespace before it. There is no case a non-alphanumeric
                // character should also be checked, like '(' or '+'
                if (wordParser.endsWithIgnoreCase(position, fragment)) {

                    char character = wordParser.character(position - fragment.length() - 1);

                    if (Character.isWhitespace(character)) {
                        proposals.addIdentifier(identifier);
                        break;
                    }
                }
            }
        }
    }

    /**
     * Adds the given JPQL identifier as a valid proposal if its role is {@link IdentifierRole#COMPOUND_FUNCTION}
     * and the beginning starts with the current word.
     *
     * @param identifier The JPQL identifier to add as a valid proposal if it passes the checks
     * @param expression The {@link Expression} represents the fragment that is before the current
     * word and it helps to filter out some of the compound identifiers
     * @param hasIs Flag indicating if the <code><b>IS</b></code> identifier was found before the word,
     * which would also be before the <code><b>NOT</b></code> identifier if it was also found
     * @param hasNot Flag indicating if the <code><b>NOT</b></code> identifier was found before the word
     */
    protected void addCompoundIdentifier(String identifier,
                                         Expression expression,
                                         boolean hasIs,
                                         boolean hasNot) {

        if (isCompoundFunction(identifier)) {

            Filter<Expression> filter = getFilter(identifier);

            // "IS <identifier>" (examples of possible identifiers: IS NULL, IS NOT NULL)
            if (hasIs && !hasNot) {
                if (identifier.startsWith("IS ") && filter.accept(expression)) {
                    addCompositeIdentifier(identifier, 0);
                }
            }
            // "NOT <identifier>" (examples of possible identifiers: NOT EMPTY, NOT BETWEEN)
            else if (!hasIs && hasNot) {
                if (identifier.startsWith("NOT ") && filter.accept(expression)) {
                    addCompositeIdentifier(identifier, 0);
                }
            }
            // "IS NOT <identifier>" (examples of possible identifiers: IS NOT NULL, IS NOT EMPTY)
            else if (hasIs && hasNot) {
                if (identifier.startsWith("IS NOT ") && filter.accept(expression)) {
                    addCompositeIdentifier(identifier, 0);
                }
            }
            // "<identifier>" (examples of possible identifiers: BETWEEN, MEMBER, MEMBER OF)
            else if (filter.accept(expression)) {
                addIdentifier(identifier);
            }
        }
    }

    /**
     * Adds the JPQL identifiers that are registered with the given {@link JPQLQueryBNF} as valid
     * proposals if their role is {@link IdentifierRole#COMPOUND_FUNCTION} and the beginning starts
     * with the current word.
     *
     * @param queryBNF The {@link JPQLQueryBNF} for which the registered JPQL identifiers will be
     * added as proposals if they pass the checks
     * @param expression The {@link Expression} represents the fragment that is before the current
     * word and it helps to filter out some of the compound identifiers
     * @param hasIs Flag indicating if the <code><b>IS</b></code> identifier was found before the word,
     * which would also be before the <code><b>NOT</b></code> identifier if it was also found
     * @param hasNot Flag indicating if the <code><b>NOT</b></code> identifier was found before the word
     */
    protected void addCompoundIdentifiers(JPQLQueryBNF queryBNF,
                                          Expression expression,
                                          boolean hasIs,
                                          boolean hasNot) {

        for (String identifier : queryBNF.getIdentifiers()) {
            addCompoundIdentifier(identifier, expression, hasIs, hasNot);
        }
    }

    /**
     * Adds the JPQL identifiers that are registered with the given {@link JPQLQueryBNF} as valid
     * proposals if their role is {@link IdentifierRole#COMPOUND_FUNCTION} and the beginning starts
     * with the current word.
     *
     * @param queryBNFId The unique identifier of the {@link JPQLQueryBNF} for which the registered
     * JPQL identifiers will be added as proposals if they pass the checks
     * @param expression The {@link Expression} represents the fragment that is before the current
     * word and it helps to filter out some of the compound identifiers
     * @param hasIs Flag indicating if the <code><b>IS</b></code> identifier was found before the word,
     * which would also be before the <code><b>NOT</b></code> identifier if it was also found
     * @param hasNot Flag indicating if the <code><b>NOT</b></code> identifier was found before the word
     */
    protected void addCompoundIdentifiers(String queryBNFId,
                                          Expression expression,
                                          boolean hasIs,
                                          boolean hasNot) {

        addCompoundIdentifiers(getQueryBNF(queryBNFId), expression, hasIs, hasNot);
    }

    /**
     * Adds the entities as possible content assist proposals but will be filtered using the current word.
     */
    protected void addEntities() {
        for (IEntity entity : queryContext.getProvider().entities()) {
            if (isValidProposal(entity.getName(), word)) {
                proposals.addEntity(entity);
            }
        }
    }

    /**
     * Adds the entities as possible content assist proposals but will be filtered using the current
     * word and the entity's type will have to be assignable from the given {@link IType}.
     *
     * @param type The {@link IType} used to filter the abstract schema types
     */
    protected void addEntities(IType type) {

        for (IEntity entity : queryContext.getProvider().entities()) {

            if (isValidProposal(entity.getName(), word) &&
                type.isAssignableTo(entity.getType())) {

                proposals.addEntity(entity);
            }
        }
    }

    /**
     * Adds the given enum constant as a valid proposal.
     *
     * @param enumType The {@link IType} of the {@link Enum}
     * @param enumConstant The enum constant to be added as a valid proposal
     */
    protected void addEnumConstant(IType enumType, String enumConstant) {
        proposals.addEnumConstant(enumType, enumConstant);
    }

    /**
     * Adds the constants of the given enum type as valid proposals if the beginning starts with the
     * given word.
     *
     * @param enumType The {@link IType} of the enum type
     * @param word The word is used to filter the enum constants, which can be <code>null</code> or
     * an empty string
     */
    protected void addEnumConstants(IType enumType, String word) {

        for (String enumConstant : enumType.getEnumConstants()) {
            if (ExpressionTools.startWithIgnoreCase(enumConstant, word)) {
                addEnumConstant(enumType, enumConstant);
            }
        }
    }

    /**
     * Adds the JPQL identifiers that were registered with the given {@link ExpressionFactory}.
     *
     * @param expressionFactory The factory for which its registered JPQL identifiers are added as
     * valid proposals, if they meet the checks
     */
    protected void addExpressionFactoryIdentifiers(ExpressionFactory expressionFactory) {
        for (String identifier : expressionFactory.identifiers()) {
            addIdentifier(identifier);
        }
    }

    /**
     * Adds the JPQL identifiers that were registered with the {@link ExpressionFactory} with the
     * given unique identifier.
     *
     * @param expressionFactoryId The unique identifier of the factory for which its registered JPQL
     * identifiers are added as valid proposals, if they meet the checks
     */
    protected void addExpressionFactoryIdentifiers(String expressionFactoryId) {
        addExpressionFactoryIdentifiers(getExpressionFactory(expressionFactoryId));
    }

    /**
     * Adds the given JPQL identifier as a valid proposal if its role is {@link IdentifierRole#FUNCTION}
     * and the beginning starts with the current word.
     *
     * @param identifier The JPQL identifier to add as a valid proposal if it passes the checks
     */
    protected void addFunctionIdentifier(String identifier) {
        if (isFunction(identifier)) {
            addIdentifier(identifier);
        }
    }

    /**
     * Adds the JPQL identifiers for which their role is {@link IdentifierRole#FUNCTION FUNCTION} by
     * determining the {@link JPQLQueryBNF} that represents the fragment for which the given {@link
     * Expression} was parsed.
     * <p>
     * For instance: "<code>SELECT e, AVG(e.name) FROM Employee e</code>" and the given expression is
     * "<code>AVG(e.name)</code>", then the BNF should be the select item BNF.
     * <p>
     * If the BNF allows for a subquery and the expression is encapsulated by parenthesis, then
     * <code><b>SELECT</b></code> will also be added.
     * <p>
     * The identification variables will also be added.
     *
     * @param expression The {@link Expression} is used to determine the {@link JPQLQueryBNF} to use
     * when retrieving the JPQL identifiers representing a function
     */
    protected void addFunctionIdentifiers(Expression expression) {

        JPQLQueryBNF queryBNF = expression.getParent().findQueryBNF(expression);

        addIdentificationVariables();
        addFunctionIdentifiers(queryBNF);

        if (isValid(queryBNF, SubqueryBNF.ID, true) && isEncapsulated(expression)) {
            addIdentifier(SELECT);
        }
    }

    /**
     * Adds the JPQL identifiers that are registered with the given {@link JPQLQueryBNF} as valid
     * proposals if their role is {@link IdentifierRole#FUNCTION} and the beginning starts with the
     * current word.
     *
     * @param queryBNF The {@link JPQLQueryBNF} for which the registered JPQL identifiers will be
     * added as proposals if they pass the checks
     */
    protected void addFunctionIdentifiers(JPQLQueryBNF queryBNF) {
        for (String identifier : queryBNF.getIdentifiers()) {
            addFunctionIdentifier(identifier);
        }
    }

    /**
     * Adds the JPQL identifiers that are registered with the given {@link JPQLQueryBNF} as valid
     * proposals if their role is {@link IdentifierRole#FUNCTION} and the beginning starts with the
     * current word.
     *
     * @param queryBNFId The unique identifier of the {@link JPQLQueryBNF} for which the registered
     * JPQL identifiers will be added as proposals if they pass the checks
     */
    protected void addFunctionIdentifiers(String queryBNFId) {
        addFunctionIdentifiers(getQueryBNF(queryBNFId));
    }

    /**
     * Adds the given identification variable as a valid proposal.
     *
     * @param identificationVariable The identification variable to add as a proposal if it passes the checks
     */
    protected void addIdentificationVariable(String identificationVariable) {

        if (ExpressionTools.stringIsNotEmpty(identificationVariable) &&
            isValidProposal(identificationVariable, word)) {

            proposals.addIdentificationVariable(identificationVariable);
        }
    }

    /**
     * Adds all the identification variables defined in the current query's <b>FROM</b> clause.
     */
    protected void addIdentificationVariables() {
        addIdentificationVariables(null, IdentificationVariableType.ALL);
    }

    /**
     * Adds the possible identification variables as valid proposals but filter them based on the
     * given type.
     * <p>
     * For instance, if the type is {@link IdentificationVariableType#LEFT}, then any identification
     * variables that have been defined before the given {@link Expression} are valid proposals, but
     * those defined after are not valid proposals.
     *
     * @param expression The {@link Expression} where the content assist was invoked, which helps to
     * determine how to stop adding identification variables
     * @param type Which type of identification variables to add as valid proposals
     */
    protected void addIdentificationVariables(Expression expression, IdentificationVariableType type) {

        for (Declaration declaration : queryContext.getDeclarations()) {
            boolean stop = type.add(this, declaration, expression);
            if (stop) {
                break;
            }
        }
    }

    /**
     * Adds the given identifier as a proposal if it passes the checks.
     *
     * @param identifier The JPQL identifier to add as a proposal
     */
    protected void addIdentifier(String identifier) {

        if (isValidVersion(identifier) &&
            isValidProposal(identifier, word)) {

            proposals.addIdentifier(identifier);
        }
    }

    /**
     * Adds the join specification identifiers as proposals.
     */
    protected void addJoinIdentifiers() {
        addIdentifier(INNER_JOIN);
        addIdentifier(INNER_JOIN_FETCH);
        addIdentifier(JOIN);
        addIdentifier(JOIN_FETCH);
        addIdentifier(LEFT_JOIN);
        addIdentifier(LEFT_JOIN_FETCH);
        addIdentifier(LEFT_OUTER_JOIN);
        addIdentifier(LEFT_OUTER_JOIN_FETCH);
    }

    /**
     * Adds the identification variables defined in the current query's <b>FROM</b> clause that are
     * declared before the given {@link Expression}.
     *
     * @param expression The {@link Expression} used to determine at which declaration to stop
     */
    protected void addLeftIdentificationVariables(Expression expression) {
        addIdentificationVariables(expression, IdentificationVariableType.LEFT);
    }

    /**
     * Adds the logical identifiers, which are <code><b>AND</b></code> and <code><b>OR</b></code>.
     */
    protected void addLogicalIdentifiers() {
        addIdentifier(AND);
        addIdentifier(OR);
    }

    /**
     * Adds the given identification variable as a proposal if it passes the checks. If an entity is
     * found, then it will be registered.
     *
     * @param identificationVariable An identification variable that is
     */
    protected void addRangeIdentificationVariable(String identificationVariable) {

        if (ExpressionTools.stringIsNotEmpty(identificationVariable) &&
            isValidProposal(identificationVariable, word)) {

            // Resolve the identification variable
            Resolver resolver = queryContext.getResolver(identificationVariable);
            IEntity entity = queryContext.getProvider().getEntity(resolver.getType());

            // The identification variable identifies an entity, add the extra information
            if (entity != null) {
                proposals.addRangeIdentificationVariable(identificationVariable, entity);
            }
            else {
                proposals.addIdentificationVariable(identificationVariable);
            }
        }
    }

    /**
     * Adds the result variables defined in the <code>SELECT</code> clause as valid proposals.
     */
    protected void addResultVariables() {
        for (String resultVariable : queryContext.getResultVariables()) {
            addIdentificationVariable(resultVariable);
        }
    }

    /**
     * Adds a virtual space on the stack.
     */
    protected final void addVirtualSpace() {
        virtualSpaces.add(SPACE_LENGTH);
    }

    /**
     * Determines whether the given {@link Expression} can be followed by an arithmetic operator.
     *
     * @param expression The {@link Expression} that found left of the cursor, which determines if
     * the arithmetic operators are appendable or not
     * @return <code>true</code> if the operators are appendable; <code>false</code> otherwise
     */
    protected boolean areArithmeticSymbolsAppendable(Expression expression) {
        return isAppendable(expression, AppendableType.ARITHMETIC);
    }

    /**
     * Determines whether the given {@link Expression} can be followed by a comparison operator.
     *
     * @param expression The {@link Expression} that found left of the cursor, which determines if
     * the comparison operators are appendable or not
     * @return <code>true</code> if the operators are appendable; <code>false</code> otherwise
     */
    protected boolean areComparisonSymbolsAppendable(Expression expression) {
        return isAppendable(expression, AppendableType.COMPARISON);
    }

    /**
     * Determines whether the given {@link Expression} can be followed by a logical operator.
     *
     * @param expression The {@link Expression} that found left of the cursor, which determines if
     * the logical operators are appendable or not
     * @return <code>true</code> if the logical identifiers are appendable; <code>false</code> otherwise
     */
    protected boolean areLogicalSymbolsAppendable(Expression expression) {
        return isAppendable(expression, AppendableType.LOGICAL);
    }

    protected abstract AcceptableTypeVisitor buildAcceptableTypeVisitor();

    protected AppendableExpressionVisitor buildAppendableExpressionVisitor() {
        return new AppendableExpressionVisitor(this);
    }

    protected Filter<Expression> buildCollectionCompoundTypeFilter() {
        return new Filter<Expression>() {
            @Override
            public boolean accept(Expression expression) {
                IType type = queryContext.getType(expression);
                TypeHelper typeHelper = queryContext.getTypeHelper();
                return typeHelper.isCollectionType(type) ||
                       typeHelper.isMapType(type);
            }
        };
    }

    protected CollectionExpressionVisitor buildCollectionExpressionVisitor() {
        return new CollectionExpressionVisitor();
    }

    protected CollectionMappingFilter buildCollectionMappingFilter() {
        return new CollectionMappingFilter();
    }

    protected ConcatExpressionCollectionHelper buildConcatExpressionCollectionHelper() {
        return new ConcatExpressionCollectionHelper(this);
    }

    protected ConditionalClauseCollectionHelper buildConditionalClauseCollectionHelper() {
        return new ConditionalClauseCollectionHelper(this);
    }

    protected ConstrutorCollectionHelper buildConstrutorCollectionHelper() {
        return new ConstrutorCollectionHelper(this);
    }

    protected DeclarationVisitor buildDeclarationVisitor() {
        return new DeclarationVisitor();
    }

    protected DefaultMappingCollector buildDefaultMappingCollector() {
        return new DefaultMappingCollector();
    }

    protected DeleteClauseCollectionHelper buildDeleteClauseCollectionHelper() {
        return new DeleteClauseCollectionHelper(this);
    }

    protected DeleteClauseStatementHelper buildDeleteClauseStatementHelper() {
        return new DeleteClauseStatementHelper(this);
    }

    protected Filter<Expression> buildDifferentComparisonFilter() {
        return new DifferentComparisonFilter();
    }

    protected DoubleEncapsulatedCollectionHelper buildDoubleEncapsulatedCollectionHelper() {
        return new DoubleEncapsulatedCollectionHelper(this);
    }

    protected EncapsulatedExpressionVisitor buildEncapsulatedExpressionVisitor() {
        return new EncapsulatedExpressionVisitor();
    }

    /**
     * Creates a new {@link QueryPosition} containing the corrected positions starting at the given
     * {@link Expression} and traversing the children at is always at the right side of the tree.
     *
     * @param invalidExpression The invalid {@link Expression} for which a new {@link QueryPosition}
     * will be calculated
     * @param startingPointExpression The {@link Expression} from which the calculation of the positions will start
     * @param virtualSpace Single element array that will be used to store the flag indicating if a
     * virtual space should be added or not
     * @return The new {@link QueryPosition} that contains the position of the cursor starting from
     * the given {@link Expression} down to the right leaf
     */
    protected QueryPosition buildEndingPositionFromInvalidExpression(Expression invalidExpression,
                                                                     Expression startingPointExpression,
                                                                     boolean[] virtualSpace) {

        EndingQueryPositionBuilder visitor = getEndingQueryPositionBuilder();

        try {

            visitor.prepare(invalidExpression);
            startingPointExpression.accept(visitor);

            virtualSpace[0] = visitor.hasVirtualSpace();
            return visitor.getQueryPosition();
        }
        finally {
            visitor.dispose();
        }
    }

    protected EndingQueryPositionBuilder buildEndingQueryPositionBuilder() {
        return new EndingQueryPositionBuilder(this);
    }

    protected EnumVisitor buildEnumVisitor() {
        return new EnumVisitor();
    }

    protected FilteringMappingCollector buildFilteringMappingCollector(AbstractPathExpression expression,
                                                                       Resolver resolver,
                                                                       Filter<IMapping> filter,
                                                                       String pattern) {

        return new FilteringMappingCollector(
            resolver,
            buildMappingFilter(expression, filter),
            pattern
        );
    }

    protected FollowingClausesVisitor buildFollowingClausesVisitor() {
        return new FollowingClausesVisitor();
    }

    protected FollowingInvalidExpressionVisitor buildFollowingInvalidExpressionVisitor() {
        return new FollowingInvalidExpressionVisitor(this);
    }

    protected FromClauseCollectionHelper buildFromClauseCollectionHelper() {
        return new FromClauseCollectionHelper(this);
    }

    protected FromClauseStatementHelper buildFromClauseStatementHelper() {
        return new FromClauseStatementHelper(this);
    }

    protected GroupByClauseCollectionHelper buildGroupByClauseCollectionHelper() {
        return new GroupByClauseCollectionHelper(this);
    }

    protected GroupByClauseStatementHelper buildGroupByClauseStatementHelper() {
        return new GroupByClauseStatementHelper(this);
    }

    protected HavingClauseStatementHelper buildHavingClauseStatementHelper() {
        return new HavingClauseStatementHelper(this);
    }

    protected IncompleteCollectionExpressionVisitor buildIncompleteCollectionExpressionVisitor() {
        return new IncompleteCollectionExpressionVisitor();
    }

    protected InvalidExpressionVisitor buildInvalidExpressionVisitor() {
        return new InvalidExpressionVisitor();
    }

    protected JoinCollectionHelper buildJoinCollectionHelper() {
        return new JoinCollectionHelper(this);
    }

    /**
     * Returns the {@link JPQLQueryBNFValidator} that can be used to validate an {@link Expression}
     * by making sure its BNF is part of the given BNF.
     *
     * @param queryBNF The BNF used to determine the validity of an {@link Expression}
     * @return A {@link JPQLQueryBNFValidator} that can determine if an {@link Expression} follows
     * the given BNF
     */
    protected JPQLQueryBNFValidator buildJPQLQueryBNFValidator(JPQLQueryBNF queryBNF) {
        return new JPQLQueryBNFValidator(queryBNF);
    }

    protected MappingCollector buildMappingCollector(AbstractPathExpression expression,
                                                     Resolver resolver,
                                                     Filter<IMapping> filter) {

        return buildFilteringMappingCollector(
            expression,
            resolver,
            filter,
            ExpressionTools.EMPTY_STRING
        );
    }

    protected Filter<IMapping> buildMappingFilter(AbstractPathExpression expression,
                                                  Filter<IMapping> filter) {

        // Wrap the filter with another Filter that will make sure only the
        // mappings with the right type will be accepted, for instance, AVG(e.|
        // can only accept state fields with a numeric type
        IType type = getAcceptableType(expression.getParent());

        // No need to filter
        if (type == null) {
            return filter;
        }

        // This will filter the property mappings
        return new AndFilter<IMapping>(new MappingTypeFilter(type, this), filter);
    }

    protected Filter<IMapping> buildMappingFilter(Expression expression) {
        MappingFilterBuilder visitor = getMappingFilterBuilder();
        try {
            expression.accept(visitor);
            return visitor.filter;
        }
        finally {
            visitor.dispose();
        }
    }

    protected MappingFilterBuilder buildMappingFilterBuilder() {
        return new MappingFilterBuilder(this);
    }

    protected Filter<Expression> buildNonCollectionCompoundTypeFilter() {
        return new Filter<Expression>() {
            @Override
            public boolean accept(Expression expression) {
                IType type = queryContext.getType(expression);
                TypeHelper typeHelper = queryContext.getTypeHelper();
                return !typeHelper.isCollectionType(type) &&
                       !typeHelper.isMapType(type);
            }
        };
    }

    protected NotExpressionVisitor buildNotExpressionVisitor() {
        return new NotExpressionVisitor();
    }

    protected OrderByClauseCollectionHelper buildOrderByClauseCollectionHelper() {
        return new OrderByClauseCollectionHelper(this);
    }

    protected OrderByClauseStatementHelper buildOrderByClauseStatementHelper() {
        return new OrderByClauseStatementHelper(this);
    }

    protected PropertyMappingFilter buildPropertyMappingFilter() {
        return new PropertyMappingFilter();
    }

    /**
     * Prepares this visitor by prepopulating it with the necessary data that is required to properly
     * gather the list of proposals based on the given caret position.
     *
     * @param position The position of the cursor within the JPQL query
     * @return The proposals that are valid choices for the given position
     */
    public ContentAssistProposals buildProposals(int position) {
        return buildProposals(position, ContentAssistExtension.NULL_HELPER);
    }

    /**
     * Prepares this visitor by prepopulating it with the necessary data that is required to properly
     * gather the list of proposals based on the given caret position.
     *
     * @param position The position of the cursor within the JPQL query
     * @param extension This extension can be used to provide additional support to JPQL content assist
     * that is outside the scope of providing proposals related to JPA metadata. It adds support for
     * providing suggestions related to class names, enum constants, table names, column names
     * @return The proposals that are valid choices for the given position
     */
    public ContentAssistProposals buildProposals(int position, ContentAssistExtension extension) {

        try {

            JPQLExpression jpqlExpression = queryContext.getJPQLExpression();
            String jpqlQuery = queryContext.getJPQLQuery();

            // Calculate the position of the cursor within the parsed tree
            queryPosition = jpqlExpression.buildPosition(jpqlQuery, position);

            // Retrieve the word from the JPQL query (which is the text before the position of the cursor)
            wordParser = new WordParser(jpqlQuery);
            wordParser.setPosition(position);
            word = wordParser.partialWord();

            // Now visit the deepest leaf first and calculate the possible proposals
            proposals = new DefaultContentAssistProposals(queryContext.getGrammar(), extension);
            queryPosition.getExpression().accept(this);

            return proposals;
        }
        finally {
            dispose();
        }
    }

    protected RangeVariableDeclarationVisitor buildRangeVariableDeclarationVisitor() {
        return new RangeVariableDeclarationVisitor();
    }

    protected ResultVariableVisitor buildResultVariableVisitor() {
        return new ResultVariableVisitor();
    }

    protected SelectClauseCollectionHelper buildSelectClauseCollectionHelper() {
        return new SelectClauseCollectionHelper(this);
    }

    protected SelectClauseStatementHelper buildSelectClauseStatementHelper() {
        return new SelectClauseStatementHelper(this);
    }

    protected SimpleFromClauseStatementHelper buildSimpleFromClauseStatementHelper() {
        return new SimpleFromClauseStatementHelper(this);
    }

    protected SimpleGroupByClauseStatementHelper buildSimpleGroupByClauseStatementHelper() {
        return new SimpleGroupByClauseStatementHelper(this);
    }

    protected SimpleHavingClauseStatementHelper buildSimpleHavingClauseStatementHelper() {
        return new SimpleHavingClauseStatementHelper(this);
    }

    protected SimpleSelectClauseCollectionHelper buildSimpleSelectClauseCollectionHelper() {
        return new SimpleSelectClauseCollectionHelper(this);
    }

    protected SimpleSelectClauseStatementHelper buildSimpleSelectClauseStatementHelper() {
        return new SimpleSelectClauseStatementHelper(this);
    }

    protected SimpleWhereClauseSelectStatementHelper buildSimpleWhereClauseSelectStatementHelper() {
        return new SimpleWhereClauseSelectStatementHelper(this);
    }

    protected SubqueryAppendableExpressionVisitor buildSubqueryAppendableExpressionVisitor() {
        return new SubqueryAppendableExpressionVisitor();
    }

    protected SubqueryVisitor buildSubqueryVisitor() {
        return new SubqueryVisitor();
    }

    protected TripleEncapsulatedCollectionHelper buildTripleEncapsulatedCollectionHelper() {
        return new TripleEncapsulatedCollectionHelper(this);
    }

    protected UpdateClauseStatementHelper buildUpdateClauseStatementHelper() {
        return new UpdateClauseStatementHelper(this);
    }

    protected UpdateItemCollectionHelper buildUpdateItemCollectionHelper() {
        return new UpdateItemCollectionHelper(this);
    }

    protected VisitParentVisitor buildVisitParentVisitor() {
        return new VisitParentVisitor(this);
    }

    protected WhenClauseConditionalClauseCollectionHelper buildWhenClauseConditionalClauseCollectionHelper() {
        return new WhenClauseConditionalClauseCollectionHelper(this);
    }

    protected WhereClauseDeleteStatementHelper buildWhereClauseDeleteStatementHelper() {
        return new WhereClauseDeleteStatementHelper(this);
    }

    protected WhereClauseSelectStatementHelper buildWhereClauseSelectStatementHelper() {
        return new WhereClauseSelectStatementHelper(this);
    }

    protected WhereClauseUpdateStatementHelper buildWhereClauseUpdateStatementHelper() {
        return new WhereClauseUpdateStatementHelper(this);
    }

    protected WithinInvalidExpressionVisitor buildWithinInvalidExpressionVisitor() {
        return new WithinInvalidExpressionVisitor();
    }

    /**
     * Disposes of the internal data.
     */
    public void dispose() {

        word          = null;
        proposals     = null;
        wordParser    = null;
        queryPosition = null;

        // Not required but during debugging, this is important to be reset
        corrections.setSize(1);
        virtualSpaces.setSize(1);
        lockedExpressions.clear();
    }

    /**
     * Retrieves the {@link RangeVariableDeclaration} that defines the entity name and identification
     * variable for the given {@link UpdateClause}.
     *
     * @return Either the {@link RangeVariableDeclaration} if the JPQL query defines it or <code>null</code>
     * if it was not defined
     */
    protected RangeVariableDeclaration findRangeVariableDeclaration(UpdateClause expression) {
        RangeVariableDeclarationVisitor visitor = getRangeVariableDeclarationVisitor();
        try {
            expression.getRangeVariableDeclaration().accept(visitor);
            return visitor.expression;
        }
        finally {
            visitor.dispose();
        }
    }

    /**
     * Determines the root {@link IType} that any type should be assignable. If the {@link IType} is
     * {@link Number}, than any subclasses will be allowed.
     *
     * @param expression The {@link Expression} to visit, including its parent hierarchy until an
     * {@link Expression} requires a certain {@link IType}
     * @return The root {@link IType} allowed or <code>null</code> if anything is allowed
     */
    protected IType getAcceptableType(Expression expression) {
        AcceptableTypeVisitor visitor = getExpressionTypeVisitor();
        try {
            expression.accept(visitor);
            return visitor.type;
        }
        finally {
            visitor.dispose();
        }
    }

    protected AppendableExpressionVisitor getAppendableExpressionVisitor() {
        AppendableExpressionVisitor helper = getHelper(AppendableExpressionVisitor.class);
        if (helper == null) {
            helper = buildAppendableExpressionVisitor();
            registerHelper(AppendableExpressionVisitor.class, helper);
        }
        return helper;
    }

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

    /**
     * Returns the visitor that collects the {@link CollectionExpression} if it's been visited.
     *
     * @return The {@link CollectionExpressionVisitor}
     * @see #buildCollectionExpressionVisitor()
     */
    protected CollectionExpressionVisitor getCollectionExpressionVisitor() {
        CollectionExpressionVisitor visitor = getHelper(CollectionExpressionVisitor.class);
        if (visitor == null) {
            visitor = buildCollectionExpressionVisitor();
            registerHelper(CollectionExpressionVisitor.class, visitor);
        }
        return visitor;
    }

    protected ConcatExpressionCollectionHelper getConcatExpressionCollectionHelper() {
        ConcatExpressionCollectionHelper helper = getHelper(ConcatExpressionCollectionHelper.class);
        if (helper == null) {
            helper = buildConcatExpressionCollectionHelper();
            registerHelper(ConcatExpressionCollectionHelper.class, helper);
        }
        return helper;
    }

    protected ConditionalClauseCollectionHelper getConditionalClauseCollectionHelper() {
        ConditionalClauseCollectionHelper helper = getHelper(ConditionalClauseCollectionHelper.class);
        if (helper == null) {
            helper = buildConditionalClauseCollectionHelper();
            registerHelper(ConditionalClauseCollectionHelper.class, helper);
        }
        return helper;
    }

    protected ConstrutorCollectionHelper getConstructorCollectionHelper() {
        ConstrutorCollectionHelper helper = getHelper(ConstrutorCollectionHelper.class);
        if (helper == null) {
            helper = buildConstrutorCollectionHelper();
            registerHelper(ConstrutorCollectionHelper.class, helper);
        }
        return helper;
    }

    protected DeclarationVisitor getDeclarationVisitor() {
        DeclarationVisitor helper = getHelper(DeclarationVisitor.class);
        if (helper == null) {
            helper = buildDeclarationVisitor();
            registerHelper(DeclarationVisitor.class, helper);
        }
        return helper;
    }

    protected MappingCollector getDefaultMappingCollector() {
        DefaultMappingCollector helper = getHelper(DefaultMappingCollector.class);
        if (helper == null) {
            helper = buildDefaultMappingCollector();
            registerHelper(DefaultMappingCollector.class, helper);
        }
        return helper;
    }

    protected DeleteClauseCollectionHelper getDeleteClauseCollectionHelper() {
        DeleteClauseCollectionHelper helper = getHelper(DeleteClauseCollectionHelper.class);
        if (helper == null) {
            helper = buildDeleteClauseCollectionHelper();
            registerHelper(DeleteClauseCollectionHelper.class, helper);
        }
        return helper;
    }

    protected DeleteClauseStatementHelper getDeleteClauseStatementHelper() {
        DeleteClauseStatementHelper helper = getHelper(DeleteClauseStatementHelper.class);
        if (helper == null) {
            helper = buildDeleteClauseStatementHelper();
            registerHelper(DeleteClauseStatementHelper.class, helper);
        }
        return helper;
    }

    protected DoubleEncapsulatedCollectionHelper getDoubleEncapsulatedCollectionHelper() {
        DoubleEncapsulatedCollectionHelper helper = getHelper(DoubleEncapsulatedCollectionHelper.class);
        if (helper == null) {
            helper = buildDoubleEncapsulatedCollectionHelper();
            registerHelper(DoubleEncapsulatedCollectionHelper.class, helper);
        }
        return helper;
    }

    protected EncapsulatedExpressionVisitor getEncapsulatedExpressionVisitor() {
        EncapsulatedExpressionVisitor helper = getHelper(EncapsulatedExpressionVisitor.class);
        if (helper == null) {
            helper = buildEncapsulatedExpressionVisitor();
            registerHelper(EncapsulatedExpressionVisitor.class, helper);
        }
        return helper;
    }

    protected EndingQueryPositionBuilder getEndingQueryPositionBuilder() {
        EndingQueryPositionBuilder visitor = getHelper(EndingQueryPositionBuilder.class);
        if (visitor == null) {
            visitor = buildEndingQueryPositionBuilder();
            registerHelper(EndingQueryPositionBuilder.class, visitor);
        }
        return visitor;
    }

    protected EnumVisitor getEnumVisitor() {
        EnumVisitor helper = getHelper(EnumVisitor.class);
        if (helper == null) {
            helper = buildEnumVisitor();
            helpers.put(EnumVisitor.class, helper);
        }
        return helper;
    }

    /**
     * Retrieves the registered {@link ExpressionFactory} that was registered for the given unique identifier.
     *
     * @param expressionFactoryId The unique identifier of the {@link ExpressionFactory} to retrieve
     * @return The {@link ExpressionFactory} mapped with the given unique identifier
     */
    protected ExpressionFactory getExpressionFactory(String expressionFactoryId) {
        return queryContext.getExpressionRegistry().getExpressionFactory(expressionFactoryId);
    }

    protected AcceptableTypeVisitor getExpressionTypeVisitor() {
        AcceptableTypeVisitor helper = getHelper(AcceptableTypeVisitor.class);
        if (helper == null) {
            helper = buildAcceptableTypeVisitor();
            registerHelper(AcceptableTypeVisitor.class, helper);
        }
        return helper;
    }

    protected Filter<Expression> getFilter(String identifier) {
        Filter<Expression> filter = identifierFilters.get(identifier);
        return (filter != null) ? filter : INVALID_IDENTIFIER_FILTER;
    }

    protected FollowingClausesVisitor getFollowingClausesVisitor() {
        FollowingClausesVisitor helper = getHelper(FollowingClausesVisitor.class);
        if (helper == null) {
            helper = buildFollowingClausesVisitor();
            helpers.put(FollowingClausesVisitor.class, helper);
        }
        return helper;
    }

    protected FollowingInvalidExpressionVisitor getFollowingInvalidExpressionVisitor() {
        FollowingInvalidExpressionVisitor helper = getHelper(FollowingInvalidExpressionVisitor.class);
        if (helper == null) {
            helper = buildFollowingInvalidExpressionVisitor();
            registerHelper(FollowingInvalidExpressionVisitor.class, helper);
        }
        return helper;
    }

    protected FromClauseCollectionHelper getFromClauseCollectionHelper() {
        FromClauseCollectionHelper helper = getHelper(FromClauseCollectionHelper.class);
        if (helper == null) {
            helper = buildFromClauseCollectionHelper();
            registerHelper(FromClauseCollectionHelper.class, helper);
        }
        return helper;
    }

    protected FromClauseStatementHelper getFromClauseStatementHelper() {
        FromClauseStatementHelper helper = getHelper(FromClauseStatementHelper.class);
        if (helper == null) {
            helper = buildFromClauseStatementHelper();
            registerHelper(FromClauseStatementHelper.class, helper);
        }
        return helper;
    }

    protected GroupByClauseCollectionHelper getGroupByClauseCollectionHelper() {
        GroupByClauseCollectionHelper helper = getHelper(GroupByClauseCollectionHelper.class);
        if (helper == null) {
            helper = buildGroupByClauseCollectionHelper();
            registerHelper(GroupByClauseCollectionHelper.class, helper);
        }
        return helper;
    }

    protected GroupByClauseStatementHelper getGroupByClauseStatementHelper() {
        GroupByClauseStatementHelper helper = getHelper(GroupByClauseStatementHelper.class);
        if (helper == null) {
            helper = buildGroupByClauseStatementHelper();
            registerHelper(GroupByClauseStatementHelper.class, helper);
        }
        return helper;
    }

    protected HavingClauseStatementHelper getHavingClauseStatementHelper() {
        HavingClauseStatementHelper helper = getHelper(HavingClauseStatementHelper.class);
        if (helper == null) {
            helper = buildHavingClauseStatementHelper();
            registerHelper(HavingClauseStatementHelper.class, helper);
        }
        return helper;
    }

    /**
     * Retrieves the helper associated with the given helper class.
     *
     * @param helperClass The Java class of the helper to retrieve
     * @return The helper being requested
     */
    @SuppressWarnings("unchecked")
    protected final <T> T getHelper(Class<T> helperClass) {
        return (T) helpers.get(helperClass);
    }

    /**
     * Retrieves the role of the given identifier. A role helps to describe the purpose of the
     * identifier in a query.
     *
     * @param identifier The identifier for which its role is requested
     * @return The role of the given identifier
     */
    protected IdentifierRole getIdentifierRole(String identifier) {
        return queryContext.getExpressionRegistry().getIdentifierRole(identifier);
    }

    protected IncompleteCollectionExpressionVisitor getIncompleteCollectionExpressionVisitor() {
        IncompleteCollectionExpressionVisitor helper = getHelper(IncompleteCollectionExpressionVisitor.class);
        if (helper == null) {
            helper = buildIncompleteCollectionExpressionVisitor();
            registerHelper(IncompleteCollectionExpressionVisitor.class, helper);
        }
        return helper;
    }

    protected InvalidExpressionVisitor getInvalidExpressionVisitor() {
        InvalidExpressionVisitor visitor = getHelper(InvalidExpressionVisitor.class);
        if (visitor == null) {
            visitor = buildInvalidExpressionVisitor();
            registerHelper(InvalidExpressionVisitor.class, visitor);
        }
        return visitor;
    }

    protected JoinCollectionHelper getJoinCollectionHelper() {
        JoinCollectionHelper helper = getHelper(JoinCollectionHelper.class);
        if (helper == null) {
            helper = buildJoinCollectionHelper();
            registerHelper(JoinCollectionHelper.class, helper);
        }
        return helper;
    }

    /**
     * Returns the latest supported JPQL grammar, which is required when checking the validity of a
     * JPQL identifier. This is due to the fact that any JPQL identifiers defined in a more recent
     * spec will be seen to be registered in version 1.0 of the spec. By returning the latest version,
     * any JPQL identifiers should have a version registered.
     *
     * @return The latest {@link JPQLGrammar} supported by the provider
     */
    protected abstract JPQLGrammar getLatestGrammar();

    protected Filter<IMapping> getMappingCollectionFilter() {
        CollectionMappingFilter helper = getHelper(CollectionMappingFilter.class);
        if (helper == null) {
            helper = buildCollectionMappingFilter();
            registerHelper(CollectionMappingFilter.class, helper);
        }
        return helper;
    }

    protected MappingFilterBuilder getMappingFilterBuilder() {
        MappingFilterBuilder helper = getHelper(MappingFilterBuilder.class);
        if (helper == null) {
            helper = buildMappingFilterBuilder();
            helpers.put(MappingFilterBuilder.class, helper);
        }
        return helper;
    }

    protected Filter<IMapping> getMappingPropertyFilter() {
        PropertyMappingFilter helper = getHelper(PropertyMappingFilter.class);
        if (helper == null) {
            helper = buildPropertyMappingFilter();
            helpers.put(PropertyMappingFilter.class, helper);
        }
        return helper;
    }

    protected NotExpressionVisitor getNotExpressionVisitor() {
        NotExpressionVisitor helper = getHelper(NotExpressionVisitor.class);
        if (helper == null) {
            helper = buildNotExpressionVisitor();
            registerHelper(NotExpressionVisitor.class, helper);
        }
        return helper;
    }

    protected OrderByClauseCollectionHelper getOrderByClauseCollectionHelper() {
        OrderByClauseCollectionHelper helper = getHelper(OrderByClauseCollectionHelper.class);
        if (helper == null) {
            helper = buildOrderByClauseCollectionHelper();
            registerHelper(OrderByClauseCollectionHelper.class, helper);
        }
        return helper;
    }

    protected OrderByClauseStatementHelper getOrderByClauseStatementHelper() {
        OrderByClauseStatementHelper helper = getHelper(OrderByClauseStatementHelper.class);
        if (helper == null) {
            helper = buildOrderByClauseStatementHelper();
            registerHelper(OrderByClauseStatementHelper.class, helper);
        }
        return helper;
    }

    /**
     * Retrieves the {@link JPQLQueryBNF} that was registered for the given unique identifier.
     *
     * @param queryBNFId The unique identifier of the {@link JPQLQueryBNF} to retrieve
     * @return The {@link JPQLQueryBNF} representing a section of the grammar
     */
    protected JPQLQueryBNF getQueryBNF(String queryBNFId) {
        return queryContext.getExpressionRegistry().getQueryBNF(queryBNFId);
    }

    protected RangeVariableDeclarationVisitor getRangeVariableDeclarationVisitor() {
        RangeVariableDeclarationVisitor helper = getHelper(RangeVariableDeclarationVisitor.class);
        if (helper == null) {
            helper = buildRangeVariableDeclarationVisitor();
            registerHelper(RangeVariableDeclarationVisitor.class, helper);
        }
        return helper;
    }

    protected ResultVariableVisitor getResultVariableVisitor() {
        ResultVariableVisitor helper = getHelper(ResultVariableVisitor.class);
        if (helper == null) {
            helper = buildResultVariableVisitor();
            registerHelper(ResultVariableVisitor.class, helper);
        }
        return helper;
    }

    protected SelectClauseCollectionHelper getSelectClauseCollectionHelper() {
        SelectClauseCollectionHelper helper = getHelper(SelectClauseCollectionHelper.class);
        if (helper == null) {
            helper = buildSelectClauseCollectionHelper();
            registerHelper(SelectClauseCollectionHelper.class, helper);
        }
        return helper;
    }

    protected SelectClauseStatementHelper getSelectClauseStatementHelper() {
        SelectClauseStatementHelper helper = getHelper(SelectClauseStatementHelper.class);
        if (helper == null) {
            helper = buildSelectClauseStatementHelper();
            registerHelper(SelectClauseStatementHelper.class, helper);
        }
        return helper;
    }

    protected SimpleFromClauseStatementHelper getSimpleFromClauseStatementHelper() {
        SimpleFromClauseStatementHelper helper = getHelper(SimpleFromClauseStatementHelper.class);
        if (helper == null) {
            helper = buildSimpleFromClauseStatementHelper();
            registerHelper(SimpleFromClauseStatementHelper.class, helper);
        }
        return helper;
    }

    protected SimpleGroupByClauseStatementHelper getSimpleGroupByClauseStatementHelper() {
        SimpleGroupByClauseStatementHelper helper = getHelper(SimpleGroupByClauseStatementHelper.class);
        if (helper == null) {
            helper = buildSimpleGroupByClauseStatementHelper();
            registerHelper(SimpleGroupByClauseStatementHelper.class, helper);
        }
        return helper;
    }

    protected SimpleHavingClauseStatementHelper getSimpleHavingClauseStatementHelper() {
        SimpleHavingClauseStatementHelper helper = getHelper(SimpleHavingClauseStatementHelper.class);
        if (helper == null) {
            helper = buildSimpleHavingClauseStatementHelper();
            registerHelper(SimpleHavingClauseStatementHelper.class, helper);
        }
        return helper;
    }

    protected SimpleSelectClauseCollectionHelper getSimpleSelectClauseCollectionHelper() {
        SimpleSelectClauseCollectionHelper helper = getHelper(SimpleSelectClauseCollectionHelper.class);
        if (helper == null) {
            helper = buildSimpleSelectClauseCollectionHelper();
            registerHelper(SimpleSelectClauseCollectionHelper.class, helper);
        }
        return helper;
    }

    protected SimpleSelectClauseStatementHelper getSimpleSelectClauseStatementHelper() {
        SimpleSelectClauseStatementHelper helper = getHelper(SimpleSelectClauseStatementHelper.class);
        if (helper == null) {
            helper = buildSimpleSelectClauseStatementHelper();
            registerHelper(SimpleSelectClauseStatementHelper.class, helper);
        }
        return helper;
    }

    protected SimpleWhereClauseSelectStatementHelper getSimpleWhereClauseSelectStatementHelper() {
        SimpleWhereClauseSelectStatementHelper helper = getHelper(SimpleWhereClauseSelectStatementHelper.class);
        if (helper == null) {
            helper = buildSimpleWhereClauseSelectStatementHelper();
            registerHelper(SimpleWhereClauseSelectStatementHelper.class, helper);
        }
        return helper;
    }

    protected SubqueryAppendableExpressionVisitor getSubqueryAppendableExpressionVisitor() {
        SubqueryAppendableExpressionVisitor helper = getHelper(SubqueryAppendableExpressionVisitor.class);
        if (helper == null) {
            helper = buildSubqueryAppendableExpressionVisitor();
            registerHelper(SubqueryAppendableExpressionVisitor.class, helper);
        }
        return helper;
    }

    protected SubqueryVisitor getSubqueryVisitor() {
        SubqueryVisitor helper = getHelper(SubqueryVisitor.class);
        if (helper == null) {
            helper = buildSubqueryVisitor();
            registerHelper(SubqueryVisitor.class, helper);
        }
        return helper;
    }

    protected TripleEncapsulatedCollectionHelper getTripleEncapsulatedCollectionHelper() {
        TripleEncapsulatedCollectionHelper helper = getHelper(TripleEncapsulatedCollectionHelper.class);
        if (helper == null) {
            helper = buildTripleEncapsulatedCollectionHelper();
            registerHelper(TripleEncapsulatedCollectionHelper.class, helper);
        }
        return helper;
    }

    protected UpdateClauseStatementHelper getUpdateClauseStatementHelper() {
        UpdateClauseStatementHelper helper = getHelper(UpdateClauseStatementHelper.class);
        if (helper == null) {
            helper = buildUpdateClauseStatementHelper();
            registerHelper(UpdateClauseStatementHelper.class, helper);
        }
        return helper;
    }

    protected UpdateItemCollectionHelper getUpdateItemCollectionHelper() {
        UpdateItemCollectionHelper helper = getHelper(UpdateItemCollectionHelper.class);
        if (helper == null) {
            helper = buildUpdateItemCollectionHelper();
            registerHelper(UpdateItemCollectionHelper.class, helper);
        }
        return helper;
    }

    protected VisitParentVisitor getVisitParentVisitor() {
        VisitParentVisitor helper = getHelper(VisitParentVisitor.class);
        if (helper == null) {
            helper = buildVisitParentVisitor();
            registerHelper(VisitParentVisitor.class, helper);
        }
        return helper;
    }

    protected WhenClauseConditionalClauseCollectionHelper getWhenClauseConditionalClauseCollectionHelper() {
        WhenClauseConditionalClauseCollectionHelper helper = getHelper(WhenClauseConditionalClauseCollectionHelper.class);
        if (helper == null) {
            helper = buildWhenClauseConditionalClauseCollectionHelper();
            registerHelper(WhenClauseConditionalClauseCollectionHelper.class, helper);
        }
        return helper;
    }

    protected WhereClauseDeleteStatementHelper getWhereClauseDeleteStatementHelper() {
        WhereClauseDeleteStatementHelper helper = getHelper(WhereClauseDeleteStatementHelper.class);
        if (helper == null) {
            helper = buildWhereClauseDeleteStatementHelper();
            registerHelper(WhereClauseDeleteStatementHelper.class, helper);
        }
        return helper;
    }

    protected WhereClauseSelectStatementHelper getWhereClauseSelectStatementHelper() {
        WhereClauseSelectStatementHelper helper = getHelper(WhereClauseSelectStatementHelper.class);
        if (helper == null) {
            helper = buildWhereClauseSelectStatementHelper();
            registerHelper(WhereClauseSelectStatementHelper.class, helper);
        }
        return helper;
    }

    protected WhereClauseUpdateStatementHelper getWhereClauseUpdateStatementHelper() {
        WhereClauseUpdateStatementHelper helper = getHelper(WhereClauseUpdateStatementHelper.class);
        if (helper == null) {
            helper = buildWhereClauseUpdateStatementHelper();
            registerHelper(WhereClauseUpdateStatementHelper.class, helper);
        }
        return helper;
    }

    protected WithinInvalidExpressionVisitor getWithinInvalidExpressionVisitor() {
        WithinInvalidExpressionVisitor helper = getHelper(WithinInvalidExpressionVisitor.class);
        if (helper == null) {
            helper = buildWithinInvalidExpressionVisitor();
            registerHelper(WithinInvalidExpressionVisitor.class, helper);
        }
        return helper;
    }

    protected boolean hasClausesDefinedBetween(Expression expression,
                                               String afterIdentifier,
                                               String beforeIdentifier) {

        FollowingClausesVisitor visitor = getFollowingClausesVisitor();

        try {
            visitor.afterIdentifier  = afterIdentifier;
            visitor.beforeIdentifier = beforeIdentifier;

            expression.accept(visitor);

            return visitor.hasFollowUpClauses;
        }
        finally {
            visitor.dispose();
        }
    }

    /**
     * Determines whether there is a virtual space to be considered or not.
     *
     * @return <code>true</code> if there is a virtual space to count as a real one or not
     */
    protected final boolean hasVirtualSpace() {
        return virtualSpaces.peek() > 0;
    }

    /**
     * Initializes this visitor.
     */
    protected void initialize() {

        helpers = new HashMap<Class<?>, Object>();
        lockedExpressions = new Stack<Expression>();

        virtualSpaces = new Stack<Integer>();
        virtualSpaces.add(0);

        corrections = new Stack<Integer>();
        corrections.add(0);

        identifierFilters = new HashMap<String, Filter<Expression>>();
        identifierFilters.put(DIFFERENT,             VALID_IDENTIFIER_FILTER);
        identifierFilters.put(EQUAL,                 VALID_IDENTIFIER_FILTER);
        identifierFilters.put(MEMBER,                VALID_IDENTIFIER_FILTER);
        identifierFilters.put(MEMBER_OF,             VALID_IDENTIFIER_FILTER);
        identifierFilters.put(NOT_MEMBER,            VALID_IDENTIFIER_FILTER);
        identifierFilters.put(NOT_MEMBER_OF,         VALID_IDENTIFIER_FILTER);
        identifierFilters.put(IS_NULL,               VALID_IDENTIFIER_FILTER);
        identifierFilters.put(IS_NOT_NULL,           VALID_IDENTIFIER_FILTER);
        identifierFilters.put(IN,                    VALID_IDENTIFIER_FILTER);
        identifierFilters.put(NOT_IN,                VALID_IDENTIFIER_FILTER);

        // 'EMPTY', 'NOT EMPTY'
        Filter<Expression> filter = buildCollectionCompoundTypeFilter();
        identifierFilters.put(IS_EMPTY,     filter);
        identifierFilters.put(IS_NOT_EMPTY, filter);

        // 'BETWEEN', 'NOT BETWEEN'
        filter = buildNonCollectionCompoundTypeFilter();
        identifierFilters.put(BETWEEN,     filter);
        identifierFilters.put(NOT_BETWEEN, filter);
        identifierFilters.put(LIKE,        filter);
        identifierFilters.put(NOT_LIKE,    filter);

        // '<', '<=', '>=', '>'
        filter = buildDifferentComparisonFilter();
        identifierFilters.put(GREATER_THAN,          filter);
        identifierFilters.put(GREATER_THAN_OR_EQUAL, filter);
        identifierFilters.put(LOWER_THAN,            filter);
        identifierFilters.put(LOWER_THAN_OR_EQUAL,   filter);
    }

    /**
     * Determines whether the given JPQL identifier used in an aggregate expression; for instance
     * <b>AND</b>.
     *
     * @param identifier The identifier to validate
     * @return <code>true</code> if the given identifier is used in an aggregate expression;
     * <code>false</code> otherwise
     */
    protected boolean isAggregate(String identifier) {
        return getIdentifierRole(identifier) == IdentifierRole.AGGREGATE;
    }

    /**
     * Determines whether a certain type of JPQL identifiers can be appended to the JPQL query based
     * on the given {@link Expression}.
     *
     * @param expression The {@link Expression} that determines what can be appended
     * @param appendableType The type of identifiers to append to the JPQL query
     * @return <code>true</code> if the JPQL identifiers with the given type can be appended to the
     * JPQL query; <code>false</code> if they cannot
     */
    protected boolean isAppendable(Expression expression, AppendableType appendableType) {
        AppendableExpressionVisitor visitor = getAppendableExpressionVisitor();
        try {
            visitor.appendableType = appendableType;
            expression.accept(visitor);
            return visitor.isAppendable();
        }
        finally {
            visitor.dispose();
        }
    }

    /**
     * Determines whether
     *
     * @param expression
     * @return
     */
    protected boolean isAppendableToCollection(Expression expression) {
        IncompleteCollectionExpressionVisitor visitor = getIncompleteCollectionExpressionVisitor();
        try {
            expression.accept(visitor);
            return visitor.isComplete();
        }
        finally {
            visitor.dispose();
        }
    }

    /**
     * Determines whether the given JPQL identifier used in a clause; for instance <b>SELECT</b>.
     *
     * @param identifier The identifier to validate
     * @return <code>true</code> if the given identifier is a clause; <code>false</code> otherwise
     */
    protected boolean isClause(String identifier) {
        return getIdentifierRole(identifier) == IdentifierRole.CLAUSE;
    }

    /**
     * Determines whether the identifiers identifying clauses can be appended to the JPQL query based
     * on the given {@link Expression}.
     *
     * @param expression The {@link Expression} that determines what can be appended
     * @return <code>true</code> if the following clauses can be appended to the JPQL query;
     * <code>false</code> if they cannot
     */
    protected boolean isClauseAppendable(Expression expression) {
        return isAppendable(expression, AppendableType.CLAUSE);
    }

    /**
     * Determines whether the given {@link Expression} is grammatically complete.
     *
     * @param expression The {@link Expression} to verify its grammar integrity
     * @return <code>true</code> if the {@link Expression} is grammatically complete;
     * <code>false</code> otherwise
     */
    protected boolean isComplete(Expression expression) {
        return isAppendable(expression, AppendableType.COMPLETE);
    }

    /**
     * Determines whether the given {@link Expression} can be used as the left side of a compound
     * expression.
     *
     * @param expression The {@link Expression} that determines if the JPQL identifiers with
     * {@link IdentifierRole#COMPOUND_FUNCTION} can be used to create a compound expression
     * @return <code>true</code> if the compound identifiers can be appended to the JPQL query;
     * <code>false</code> if they cannot
     */
    protected boolean isCompoundable(Expression expression) {
        return isAppendable(expression, AppendableType.COMPOUNDABLE);
    }

    /**
     * Determines whether the given JPQL identifier used in a compound expression; an example would
     * be <b>BETWEEN</b> or <b>MEMBER</b>.
     *
     * @param identifier The identifier to validate
     * @return <code>true</code> if the given identifier is used in a compound expression;
     * <code>false</code> otherwise
     */
    protected boolean isCompoundFunction(String identifier) {

        // Only the full JPQL identifier is valid
        if (identifier == IS || identifier == OF) {
            return false;
        }

        return getIdentifierRole(identifier) == IdentifierRole.COMPOUND_FUNCTION;
    }

    /**
     * Determines whether the given {@link AbstractPathExpression} is found within a declaration expression.
     *
     * @param expression The {@link AbstractPathExpression} to visit
     * @return <code>true</code> if the visited {@link CollectionValuedPathExpression} is owned by
     * a {@link RangeVariableDeclaration}, which indicates it is used to define the "root" object;
     * <code>false</code> if it is not
     */
    protected boolean isDeclaration(AbstractPathExpression expression) {
        DeclarationVisitor visitor = getDeclarationVisitor();
        try {
            expression.accept(visitor);
            return visitor.isDeclaration();
        }
        finally {
            visitor.dispose();
        }
    }

    /**
     * Determines whether the given {@link Expression} is being encapsulated or not.
     *
     * @param expression The {@link Expression} to scan for encapsulation
     * @return <code>true</code> if the given {@link Expression} is within parenthesis;
     * <code>false</code> otherwise
     */
    protected boolean isEncapsulated(Expression expression) {
        EncapsulatedExpressionVisitor visitor = getEncapsulatedExpressionVisitor();
        try {
            expression.accept(visitor);
            return visitor.isEncapsulated();
        }
        finally {
            visitor.dispose();
        }
    }

    /**
     * Determines whether the given {@link AbstractPathExpression} could potentially represent a
     * fully qualified enum constant, which is dictated by the location of the path expression within
     * the query. Only a few location allows an enum constant.
     *
     * @param expression The {@link AbstractPathExpression} to visit
     * @return <code>true</code> if the path expression represents a enum constant;
     * <code>false</code> otherwise
     */
    protected boolean isEnumAllowed(AbstractPathExpression expression) {
        EnumVisitor visitor = getEnumVisitor();
        try {
            visitor.pathExpression = expression;
            expression.accept(visitor);
            return visitor.isValid();
        }
        finally {
            visitor.dispose();
        }
    }

    /**
     * Determines whether the given {@link Expression} is preceded by an invalid expression.
     *
     * @param expression The {@link Expression} to visit
     * @return <code>true</code> if the visited {@link Expression} is part of a collection of
     * expressions and an invalid expression precede it; <code>false</code> otherwise
     */
    protected boolean isFollowingInvalidExpression(Expression expression) {
        FollowingInvalidExpressionVisitor visitor = getFollowingInvalidExpressionVisitor();
        try {
            visitor.expression = expression;
            expression.accept(visitor);
            return visitor.isFollowingInvalidExpression();
        }
        finally {
            visitor.dispose();
        }
    }

    /**
     * Determines whether the given JPQL identifier is a function, an example would be <b>AVG</b>.
     *
     * @param identifier The identifier to validate
     * @return <code>true</code> if the given identifier is a function; <code>false</code> otherwise
     */
    protected boolean isFunction(String identifier) {
        return getIdentifierRole(identifier) == IdentifierRole.FUNCTION;
    }

    /**
     * Determines whether the given {@link Expression} is in a subquery or in the top-level query.
     *
     * @param expression The {@link Expression} to visit its parent hierarchy
     * @return <code>true</code> if the owning query is a subquery; <code>false</code> if it's the
     * top-level query
     */
    protected boolean isInSubquery(Expression expression) {
        SubqueryVisitor visitor = getSubqueryVisitor();
        try {
            expression.accept(visitor);
            return visitor.isInSubquery();
        }
        finally {
            visitor.dispose();
        }
    }

    /**
     * Determines whether the given {@link Expression} represents an invalid fragment.
     *
     * @param expression The {@link Expression} to visit
     * @return <code>true</code> if the {@link Expression} is an invalid fragment;
     * <code>false</code> otherwise
     */
    protected boolean isInvalidExpression(Expression expression) {
        InvalidExpressionVisitor visitor = getInvalidExpressionVisitor();
        try {
            expression.accept(visitor);
            return visitor.isInvalid();
        }
        finally {
            visitor.dispose();
        }
    }

    /**
     * Determines whether a <code><b>JOIN FETCH</b></code> expression can be identified by with an
     * identification variable or not.
     *
     * @return <code>true</code> if the expression can have an identification variable;
     * <code>false</code> otherwise
     */
    protected abstract boolean isJoinFetchIdentifiable();

    /**
     * Determines whether the given {@link Expression} has been set has the lock to prevent an
     * infinite recursion.
     *
     * @param expression The {@link Expression} to check if it is locked
     * @return <code>true</code> if the given {@link Expression} has been marked as locked;
     * <code>false</code> otherwise
     */
    protected boolean isLocked(Expression expression) {
        return !lockedExpressions.empty() && (lockedExpressions.peek() == expression);
    }

    /**
     * Determines whether the given {@link Expression} represents the negated expression.
     *
     * @param expression The {@link Expression} to visit
     * @return <code>true</code> if the {@link Expression} is {@link NotExpression};
     * <code>false</code> otherwise
     */
    protected boolean isNotExpression(Expression expression) {
        NotExpressionVisitor visitor = getNotExpressionVisitor();
        try {
            expression.accept(visitor);
            return visitor.isNotExpression();
        }
        finally {
            visitor.dispose();
        }
    }

    /**
     * Determines whether the given position is within the given word.
     * <p>
     * Example: position=0, word="JPQL" {@literal =>} true
     * Example: position=1, word="JPQL" {@literal =>} true
     * Example: position=4, word="JPQL" {@literal =>} true
     * Example: position=5, word="JPQL" {@literal =>} true
     * Example: position=5, offset 2, (actual cursor position is 3), word="JPQL" {@literal =>} true
     *
     * @param position The position of the cursor
     * @param offset The offset to adjust the position
     * @param word The word to check if the cursor is positioned in it
     * @return <code>true</code> if the given position is within the given word;
     * <code>false</code> otherwise
     */
    protected boolean isPositionWithin(int position, int offset, String word) {
        return (position >= offset) && (position - offset <= word.length());
    }

    /**
     * Determines whether the given position is within the given word.
     * <p>
     * Example: position=0, word="JPQL" {@literal =>} true
     * Example: position=1, word="JPQL" {@literal =>} true
     * Example: position=4, word="JPQL" {@literal =>} true
     * Example: position=5, word="JPQL" {@literal =>} true
     *
     * @param position The position of the cursor
     * @param word The word to check if the cursor is positioned in it
     * @return <code>true</code> if the given position is within the given word;
     * <code>false</code> otherwise
     */
    protected boolean isPositionWithin(int position, String word) {
        return isPositionWithin(position, 0, word);
    }

    /**
     * Determines whether the JPQL identifier starting a subquery (<code><b>SELECT</b></code>) can
     * be appended based on the given {@link Expression} which is preceding the position of the cursor.
     *
     * @param expression The {@link Expression} that precedes the position of the cursor
     * @return <code>true</code> if a subquery can be appended; <code>false</code> otherwise
     */
    protected boolean isSubqueryAppendable(Expression expression) {
        AbstractAppendableExpressionVisitor visitor = getSubqueryAppendableExpressionVisitor();
        try {
            expression.accept(visitor);
            return visitor.isAppendable();
        }
        finally {
            visitor.dispose();
        }
    }

    /**
     * Determines whether the given {@link Expression} part is an expression of the given query BNF.
     *
     * @param expression The {@link Expression} to validate based on the query BNF
     * @param queryBNF
     * @return <code>true</code> if the {@link Expression} part is a child of the given query BNF;
     * <code>false</code> otherwise
     */
    protected boolean isValid(Expression expression, JPQLQueryBNF queryBNF) {
        JPQLQueryBNFValidator validator = buildJPQLQueryBNFValidator(queryBNF);
        try {
            expression.accept(validator);
            return validator.isValid();
        }
        finally {
            validator.dispose();
        }
    }

    /**
     * Determines whether the given {@link Expression} part is an expression of the given query BNF.
     *
     * @param expression The {@link Expression} to validate based on the query BNF
     * @param queryBNFId
     * @return <code>true</code> if the {@link Expression} part is a child of the given query BNF;
     * <code>false</code> otherwise
     */
    protected boolean isValid(Expression expression, String queryBNFId) {
        return isValid(expression, getQueryBNF(queryBNFId));
    }

    /**
     * Determines whether the given {@link JPQLQueryBNF} part is the given parent {@link JPQLQueryBNF}.
     *
     * @param parentQueryBNF The "root" of the BNF used to determine if the other is a descendant
     * @param queryBNF The BNF to check if it is a descendant of the parent
     * @return <code>true</code> if the {@link JPQLQueryBNF} is a descendant of the given parent
     * {@link JPQLQueryBNF}; <code>false</code> otherwise
     */
    protected boolean isValid(JPQLQueryBNF parentQueryBNF, JPQLQueryBNF queryBNF) {
        return isValid(parentQueryBNF, queryBNF, false);
    }

    /**
     * Determines whether the given {@link JPQLQueryBNF} part is the given parent {@link JPQLQueryBNF}.
     *
     * @param parentQueryBNF The "root" of the BNF used to determine if the other is a descendant
     * @param queryBNF The BNF to check if it is a descendant of the parent
     * @param bypassCompound Indicates whether a {@link JPQLQueryBNF} representing a compound
     * expression should be considered when doing the validation
     * @return <code>true</code> if the {@link JPQLQueryBNF} is a descendant of the given parent
     * {@link JPQLQueryBNF}; <code>false</code> otherwise
     */
    protected boolean isValid(JPQLQueryBNF parentQueryBNF, JPQLQueryBNF queryBNF, boolean bypassCompound) {
        JPQLQueryBNFValidator validator = buildJPQLQueryBNFValidator(parentQueryBNF);
        try {
            validator.setBypassCompound(bypassCompound);
            validator.validate(queryBNF);
            return validator.isValid();
        }
        finally {
            validator.dispose();
        }
    }

    /**
     * Determines whether the given {@link JPQLQueryBNF} part is the given parent {@link JPQLQueryBNF}.
     *
     * @param parentQueryBNF The "root" of the BNF used to determine if the other is a descendant
     * @param queryBNFId The unique identifier of the {@link JPQLQueryBNF} to check if it is a
     * descendant of the parent
     * @param bypassCompound Indicates whether a {@link JPQLQueryBNF} representing a compound
     * expression should be considered when doing the validation
     * @return <code>true</code> if the {@link JPQLQueryBNF} is a descendant of the given parent
     * {@link JPQLQueryBNF}; <code>false</code> otherwise
     */
    protected boolean isValid(JPQLQueryBNF parentQueryBNF, String queryBNFId, boolean bypassCompound) {
        return isValid(parentQueryBNF, getQueryBNF(queryBNFId), bypassCompound);
    }

    /**
     * Determines whether the given proposal is a valid, which is based on the content of the given
     * word. If the word is not an empty string, the proposal must start with the content of the word.
     *
     * @param proposal The proposal to validate
     * @param word The word, which is what was parsed before the position of the cursor
     * @return <code>true</code> if the proposal is valid; <code>false</code> otherwise
     */
    protected boolean isValidProposal(String proposal, String word) {

        // There is no word to match the first letters
        if (word.length() == 0) {
            return true;
        }

        char character = word.charAt(0);

        if (character == '+' ||
            character == '-' ||
            character == '*' ||
            character == '/') {

            return true;
        }

        // The word is longer than the proposal
        if (word.length() > proposal.length()) {
            return false;
        }

        // Check to see if the proposal starts with the word
        for (int index = 0, length = word.length(); index < length; index++) {

            char character1 = proposal.charAt(index);
            char character2 = word  .charAt(index);

            // If characters don't match but case may be ignored, try converting
            // both characters to uppercase. If the results match, then the
            // comparison scan should continue
            char upperCase1 = Character.toUpperCase(character1);
            char upperCase2 = Character.toUpperCase(character2);

            if (upperCase1 != upperCase2) {
                return false;
            }

            // Unfortunately, conversion to uppercase does not work properly for
            // the Georgian alphabet, which has strange rules about case
            // conversion. So we need to make one last check before exiting
            if (Character.toLowerCase(upperCase1) != Character.toLowerCase(upperCase2)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Determines whether the given JPQL identifier can be a valid proposal, i.e. if it's part of the
     * grammar of the JPA version that was used to parse the JPQL query.
     *
     * @param identifier The JPQL identifier to validate
     * @return <code>true</code> if the given identifier is part of the current JPA version or was
     * defined in previous release; <code>false</code> otherwise
     */
    protected boolean isValidVersion(String identifier) {
        JPAVersion identifierVersion = getLatestGrammar().getExpressionRegistry().getIdentifierVersion(identifier);
        return queryContext.getJPAVersion().isNewerThanOrEqual(identifierVersion);
    }

    /**
     * Determines whether the given {@link Expression} is part of an invalid fragment
     *
     * @param expression The {@link Expression} to verify its location within the JPQL query
     * @return <code>true</code> if the given {@link Expression} is within an invalid fragment;
     * <code>false</code> if it is not
     */
    protected boolean isWithinInvalidExpression(Expression expression) {
        WithinInvalidExpressionVisitor validator = getWithinInvalidExpressionVisitor();
        try {
            expression.accept(validator);
            return validator.isWithinInvalidExpression();
        }
        finally {
            validator.dispose();
        }
    }

    /**
     * Registers the given helper associated with the given helper class.
     *
     * @param helperClass The Java class of the helper to retrieve
     * @param helper The helper being registered
     * @see #getHelper(Class)
     */
    protected final <T> void registerHelper(Class<T> helperClass, T helper) {
        helpers.put(helperClass, helper);
    }

    /**
     * Removes the last virtual space from the stack.
     */
    protected final void removeVirtualSpace() {
        virtualSpaces.pop();
    }

    @Override
    public String toString() {
        return proposals.toString();
    }

    @Override
    public void visit(AbsExpression expression) {
        super.visit(expression);
        visitSingleEncapsulatedExpression(expression, IdentificationVariableType.ALL);
    }

    @Override
    public void visit(AbstractSchemaName expression) {

        // First visit with the adjustment
        corrections.add(queryPosition.getPosition(expression));
        super.visit(expression);
        corrections.pop();

        // Now visit without the adjustment
        super.visit(expression);
    }

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

    @Override
    public void visit(AllOrAnyExpression expression) {
        super.visit(expression);
        visitSingleEncapsulatedExpression(expression, IdentificationVariableType.NONE, ALL, ANY, SOME);
    }

    @Override
    public void visit(AndExpression expression) {
        super.visit(expression);
        visitLogicalExpression(expression);
    }

    @Override
    public void visit(ArithmeticFactor expression) {
        super.visit(expression);
        int position = queryPosition.getPosition(expression) - corrections.peek();
        int length = 1;

        if (position == length) {
            addIdentificationVariables();
            addFunctionIdentifiers(ArithmeticPrimaryBNF.ID);
        }
        else if (expression.hasSpaceAfterArithmeticOperator() || hasVirtualSpace()) {
            length++;

            if (position == length) {
                addIdentificationVariables();
                addFunctionIdentifiers(ArithmeticPrimaryBNF.ID);
            }
        }
    }

    @Override
    public void visit(AvgFunction expression) {
        super.visit(expression);
        visitAggregateFunction(expression);
    }

    @Override
    public void visit(BadExpression expression) {
        super.visit(expression);
        visitInvalidExpression(expression);
    }

    @Override
    public void visit(BetweenExpression expression) {
        super.visit(expression);

        int position = queryPosition.getPosition(expression) - corrections.peek();
        int length = 0;

        if (expression.hasExpression()) {
            length += expression.getExpression().getLength() + SPACE_LENGTH;
        }

        // Within "NOT BETWEEN" or "BETWEEN"
        if (expression.hasNot() && isPositionWithin(position, length, NOT_BETWEEN) ||
           !expression.hasNot() && isPositionWithin(position, length, BETWEEN)) {

            proposals.addIdentifier(BETWEEN);
            proposals.addIdentifier(NOT_BETWEEN);
        }
        // After "BETWEEN "
        else if (expression.hasSpaceAfterBetween()) {
            length += expression.getIdentifier().length() + SPACE_LENGTH;

            // TODO: Check for the BETWEEN's expression type
            // Right after "BETWEEN "
            if (position == length) {
                addIdentificationVariables();
                addFunctionIdentifiers(expression.getBoundExpressionQueryBNFId());
            }

            // After lower bound
            if (expression.hasLowerBoundExpression()) {

                // Check for something like "<lower bound> <word>"
                int lowerBoundLength = expression.getLowerBoundExpression().getLength();

                if (!expression.hasAnd() &&
                    (position > length) && (position < length + lowerBoundLength) &&
                    isAppendableToCollection(expression.getLowerBoundExpression())) {

                    addIdentifier(AND);
                }

                length += lowerBoundLength;

                if (expression.hasSpaceAfterLowerBound()) {
                    length++;

                    // Right before "AND"
                    if (position == length) {
                        proposals.addIdentifier(AND);
                    }
                    else {
                        // Within "AND"
                        if (expression.hasAnd() && isPositionWithin(position, length, AND)) {
                            proposals.addIdentifier(AND);
                        }
                        // After "AND "
                        else if (expression.hasSpaceAfterAnd()) {
                            length += AND.length() + SPACE_LENGTH;

                            // TODO: Check for the BETWEEN's expression type
                            if (position == length) {
                                addIdentificationVariables();
                                addFunctionIdentifiers(InternalBetweenExpressionBNF.ID);
                            }
                        }
                        else if (!expression.hasAnd() &&
                                  expression.hasUpperBoundExpression()) {

                            length += expression.getUpperBoundExpression().getLength();

                            if (position == length) {
                                addIdentifier(AND);
                            }
                        }
                    }
                }
            }
        }
    }

    @Override
    public void visit(CaseExpression expression) {
        super.visit(expression);
        int position = queryPosition.getPosition(expression) - corrections.peek();

        // Within "CASE"
        if (isPositionWithin(position, CASE)) {
            addIdentifier(CASE);
            addIdentificationVariables();
            addFunctionIdentifiers(expression.getParent().findQueryBNF(expression));
        }
        // After "CASE "
        else if (expression.hasSpaceAfterCase()) {
            int length = CASE.length() + SPACE_LENGTH;

            // Right after "CASE "
            if (position == length) {
                addIdentificationVariables();
                addFunctionIdentifiers(CaseOperandBNF.ID);
                proposals.addIdentifier(WHEN);
            }

            // After "<case operand> "
            if (expression.hasCaseOperand() &&
                expression.hasSpaceAfterCaseOperand()) {

                length += expression.getCaseOperand().getLength() + SPACE_LENGTH;

                // Right after "<case operand> "
                if (position == length) {
                    proposals.addIdentifier(WHEN);
                }
            }

            // After "<when clauses> "
            if (expression.hasWhenClauses() &&
                expression.hasSpaceAfterWhenClauses()) {

                length += expression.getWhenClauses().getLength() + SPACE_LENGTH;

                // Right after "<when clauses> "
                if (isPositionWithin(position, length, ELSE)) {
                    proposals.addIdentifier(ELSE);
                }

                // After "ELSE "
                if (expression.hasElse() &&
                    expression.hasSpaceAfterElse()) {

                    length += ELSE.length() + SPACE_LENGTH;

                    // Right after "ELSE "
                    if (position == length) {
                        addIdentificationVariables();
                        addFunctionIdentifiers(ScalarExpressionBNF.ID);
                    }

                    // After "<else expression> "
                    if (expression.hasElseExpression() &&
                        expression.hasSpaceAfterElseExpression()) {

                        length += expression.getElseExpression().getLength() + SPACE_LENGTH;

                        // Right after "<else expression> "
                        if (isPositionWithin(position, length, END)) {
                            proposals.addIdentifier(END);
                        }
                    }
                }
            }
        }
    }

    @Override
    public void visit(CoalesceExpression expression) {
        super.visit(expression);

        if (isFollowingInvalidExpression(expression)) {
            return;
        }

        int position = queryPosition.getPosition(expression) - corrections.peek();

        // Within the identifier
        if (isPositionWithin(position, COALESCE)) {
            addIdentifier(COALESCE);
            addIdentificationVariables();
            addFunctionIdentifiers(expression.getParent().findQueryBNF(expression));
        }
        // Right after "<identifier>("
        else if (expression.hasLeftParenthesis()) {
            int length = COALESCE.length() + 1 /* '(' */;

            if (position == length) {
                addIdentificationVariables();
                addFunctionIdentifiers(expression.getEncapsulatedExpressionQueryBNFId());
            }
        }
    }

    @Override
    public void visit(CollectionExpression expression) {
        if (!isLocked(expression)) {
            super.visit(expression);
        }
    }

    @Override
    public void visit(CollectionMemberDeclaration expression) {
        super.visit(expression);
        int position = queryPosition.getPosition(expression) - corrections.peek();

        // Within "IN"
        if (isPositionWithin(position, IN)) {

            if (!isWithinInvalidExpression(expression)) {
                proposals.addIdentifier(IN);
            }

            addIdentificationVariables();
            addFunctionIdentifiers(expression.getParent().findQueryBNF(expression));
        }

        // In a subquery only
        // After "IN "
        if (isInSubquery(expression) && expression.hasSpaceAfterIn()) {
            int length = IN.length() + SPACE_LENGTH;

            // Right after "IN "
            if (position == length) {
                // TODO: Type.SuperQueryIdentificationVariable
                addLeftIdentificationVariables(expression);
            }
        }
        // In a top-level query or subquery
        // After "IN("
        else if (expression.hasLeftParenthesis()) {
            int length = IN.length() + 1 /* '(' */;

            // Right after "IN("
            if (position == length) {
                addLeftIdentificationVariables(expression);
                addFunctionIdentifiers(CollectionValuedPathExpressionBNF.ID);
            }

            // After "<collection-valued path expression>)"
            if (expression.hasRightParenthesis()) {
                length += expression.getCollectionValuedPathExpression().getLength() + 1 /* ')' */;

                // Right after "<collection-valued path expression>)"
                if ((position == length) && !expression.hasSpaceAfterRightParenthesis()) {
                    proposals.addIdentifier(AS);
                }

                if (expression.hasSpaceAfterRightParenthesis()) {
                    length++;
                }

                // Within "AS"
                if (isPositionWithin(position, length, AS)) {
                    proposals.addIdentifier(AS);
                }
            }
        }
    }

    @Override
    public void visit(CollectionMemberExpression expression) {
        super.visit(expression);
        int position = queryPosition.getPosition(expression) - corrections.peek();
        String identifier = expression.getIdentifier();
        int length = 0;

        if (expression.hasEntityExpression()) {
            length = expression.getEntityExpression().getLength() + SPACE_LENGTH;
        }

        // Within the <identifier>
        if (isPositionWithin(position, length, identifier)) {
            proposals.addIdentifier(NOT_MEMBER);
            proposals.addIdentifier(NOT_MEMBER_OF);
            proposals.addIdentifier(MEMBER);
            proposals.addIdentifier(MEMBER_OF);
        }
        // After the <identifier>
        else if (expression.hasOf() && expression.hasSpaceAfterOf() ||
                !expression.hasOf() && expression.hasSpaceAfterMember()) {

            length += identifier.length() + SPACE_LENGTH;

            // Right after the <identifier>
            if (position == length) {
                if (!expression.hasOf()) {
                    addIdentifier(OF);
                }
                addIdentificationVariables();
            }
        }
    }

    @Override
    public void visit(CollectionValuedPathExpression expression) {
        super.visit(expression);

        if (!isFollowingInvalidExpression(expression)) {

            visitPathExpression(expression);

            if (isDeclaration(expression)) {
                proposals.setClassNamePrefix(word, ClassType.INSTANTIABLE);
            }
        }
    }

    @Override
    public void visit(ComparisonExpression expression) {
        super.visit(expression);
        int position = queryPosition.getPosition(expression) - corrections.peek();
        int length = 0;

        if (expression.hasLeftExpression()) {
            length += expression.getLeftExpression().getLength() + SPACE_LENGTH;
        }

        // Within the comparison operator
        if (isPositionWithin(position, length, expression.getComparisonOperator())) {
            addExpressionFactoryIdentifiers(ComparisonExpressionFactory.ID);
        }

        // After the comparison operator
        length += expression.getComparisonOperator().length();

        if (expression.hasSpaceAfterIdentifier()) {
            length++;
        }

        // Right after the comparison operator
        if (position == length) {
            addIdentificationVariables();
            addFunctionIdentifiers(expression.getRightExpressionQueryBNFId());
            addClauseIdentifiers(expression.getRightExpressionQueryBNFId());
        }
    }

    @Override
    public void visit(ConcatExpression expression) {
        super.visit(expression);
        visitCollectionExpression(expression, CONCAT, getConcatExpressionCollectionHelper());
    }

    @Override
    public void visit(ConstructorExpression expression) {
        super.visit(expression);
        int position = queryPosition.getPosition(expression) - corrections.peek();

        // NEW
        if (isPositionWithin(position, NEW)) {
            proposals.addIdentifier(NEW);
        }
        // After "NEW "
        else if (expression.hasSpaceAfterNew()) {
            int length = NEW.length() + SPACE_LENGTH;
            String className = expression.getClassName();
            int classNameLength = className.length();

            // Right after "NEW " or within the fully qualified class name
            if ((position >= length) && (position <= length + classNameLength)) {
                proposals.setClassNamePrefix(className.substring(0, position - length), ClassType.INSTANTIABLE);
            }
            // After "("
            else if (expression.hasLeftParenthesis()) {
                length += classNameLength + SPACE_LENGTH;

                // Right after "("
                if (position == length) {
                    addIdentificationVariables();
                    addFunctionIdentifiers(ConstructorItemBNF.ID);
                }
                else {
                    visitCollectionExpression(expression, NEW, getConstructorCollectionHelper());
                }
            }
        }
    }

    @Override
    public void visit(CountFunction expression) {
        super.visit(expression);
        visitAggregateFunction(expression);
    }

    @Override
    public void visit(DateTime expression) {
        super.visit(expression);
        int position = queryPosition.getPosition(expression) - corrections.peek();

        // Within the identifier
        if (expression.isCurrentDate()      && isPositionWithin(position, CURRENT_DATE) ||
            expression.isCurrentTime()      && isPositionWithin(position, CURRENT_TIME) ||
            expression.isCurrentTimestamp() && isPositionWithin(position, CURRENT_TIMESTAMP)) {

            proposals.addIdentifier(CURRENT_DATE);
            proposals.addIdentifier(CURRENT_TIME);
            proposals.addIdentifier(CURRENT_TIMESTAMP);

            addFunctionIdentifiers(expression.getParent().findQueryBNF(expression));
        }
    }

    @Override
    public void visit(DeleteClause expression) {
        if (!isLocked(expression)) {
            super.visit(expression);
            visitCollectionExpression(expression, DELETE_FROM, getDeleteClauseCollectionHelper());
        }
    }

    @Override
    public void visit(DeleteStatement expression) {
        if (!isLocked(expression)) {
            super.visit(expression);
            visitStatement(expression, getDeleteClauseStatementHelper());
        }
    }

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

    @Override
    public void visit(EmptyCollectionComparisonExpression expression) {
        super.visit(expression);
        int position = queryPosition.getPosition(expression) - corrections.peek();
        int length = 0;

        if (expression.hasExpression()) {
            length = expression.getExpression().getLength() + SPACE_LENGTH;
        }

        // Within the <identifier>
        if (isPositionWithin(position, length, expression.getIdentifier())) {
            proposals.addIdentifier(IS_EMPTY);
            proposals.addIdentifier(IS_NOT_EMPTY);
        }
    }

    @Override
    public void visit(EntityTypeLiteral expression) {

        // Adjust the position to be the "beginning" of the expression by adding a "correction"
        corrections.add(queryPosition.getPosition(expression));
        super.visit(expression);
        corrections.pop();

        // Add the possible abstract schema names
        addEntities();
    }

    @Override
    public void visit(EntryExpression expression) {
        super.visit(expression);
        visitSingleEncapsulatedExpression(expression, IdentificationVariableType.COLLECTION);
    }

    @Override
    public void visit(ExistsExpression expression) {
        super.visit(expression);
        visitSingleEncapsulatedExpression(expression, IdentificationVariableType.NONE, EXISTS, NOT_EXISTS);
    }

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

    @Override
    public void visit(FromClause expression) {
        if (!isLocked(expression)) {
            super.visit(expression);
            visitCollectionExpression(expression, FROM, getFromClauseCollectionHelper());
        }
    }

    @Override
    public void visit(FunctionExpression expression) {
        super.visit(expression);
        visitSingleEncapsulatedExpression(expression, IdentificationVariableType.ALL);
    }

    @Override
    public void visit(GroupByClause expression) {
        if (!isLocked(expression)) {
            super.visit(expression);
            visitCollectionExpression(expression, GROUP_BY, getGroupByClauseCollectionHelper());
        }
    }

    @Override
    public void visit(HavingClause expression) {
        if (!isLocked(expression)) {
            super.visit(expression);
            visitCollectionExpression(expression, expression.getIdentifier(), getConditionalClauseCollectionHelper());
        }
    }

    @Override
    public void visit(IdentificationVariable expression) {

        // First visit with the adjustment
        corrections.add(queryPosition.getPosition(expression));
        super.visit(expression);
        corrections.pop();

        // Now visit without the adjustment
        super.visit(expression);
    }

    @Override
    public void visit(IdentificationVariableDeclaration expression) {
        super.visit(expression);
        int position = queryPosition.getPosition(expression) - corrections.peek();

        if ((position > 0) && (expression.hasSpace() || hasVirtualSpace())) {

            Expression rangeVariableDeclaration = expression.getRangeVariableDeclaration();
            int length = rangeVariableDeclaration.getLength() + SPACE_LENGTH;

            if (position == length) {
                if (isComplete(rangeVariableDeclaration)) {
                    addJoinIdentifiers();
                }
            }
            else {
                visitCollectionExpression(expression, ExpressionTools.EMPTY_STRING, getJoinCollectionHelper());
            }
        }
    }

    @Override
    public void visit(IndexExpression expression) {
        super.visit(expression);
        visitSingleEncapsulatedExpression(expression, IdentificationVariableType.ALL);
    }

    @Override
    public void visit(InExpression expression) {
        expression.accept(getVisitParentVisitor());
        int position = queryPosition.getPosition(expression) - corrections.peek();
        int length = 0;

        if (expression.hasExpression()) {
            length = expression.getExpression().getLength() + SPACE_LENGTH;
        }

        // Within "IN"
        if (isPositionWithin(position, length, expression.getIdentifier())) {

            // Make sure there is an expression left of 'IN'
            if (length > 2) {
                proposals.addIdentifier(IN);
                proposals.addIdentifier(NOT_IN);
            }

            addIdentificationVariables();
            addFunctionIdentifiers(expression.getParent().findQueryBNF(expression));
        }
        // After "IN("
        else if (expression.hasLeftParenthesis()) {
            length += expression.getIdentifier().length() + SPACE_LENGTH;

            // Right after "IN("
            if (position == length) {
                addFunctionIdentifiers(InExpressionItemBNF.ID);
                proposals.addIdentifier(SELECT);
            }
        }
    }

    @Override
    public void visit(InputParameter expression) {
        // No content assist can be provider for an input parameter
        super.visit(expression);
    }

    @Override
    public void visit(Join expression) {
        super.visit(expression);
        int position = queryPosition.getPosition(expression) - corrections.peek();
        String identifier = expression.getIdentifier();
        boolean joinFetch = expression.hasFetch();

        // Within "<join>"
        if (isPositionWithin(position, identifier)) {

            // Add JOIN identifiers
            proposals.addIdentifier(JOIN);
            proposals.addIdentifier(INNER_JOIN);
            proposals.addIdentifier(LEFT_JOIN);
            proposals.addIdentifier(LEFT_OUTER_JOIN);

            // Add JOIN FETCH identifiers if allowed or
            // if there is no 'AS identification_variable'
            if (isJoinFetchIdentifiable() ||
               !expression.hasAs() && !expression.hasIdentificationVariable()) {

                proposals.addIdentifier(JOIN_FETCH);
                proposals.addIdentifier(INNER_JOIN_FETCH);
                proposals.addIdentifier(LEFT_JOIN_FETCH);
                proposals.addIdentifier(LEFT_OUTER_JOIN_FETCH);
            }
        }
        // After "<join> "
        else if (expression.hasSpaceAfterJoin()) {
            int length = identifier.length() + SPACE_LENGTH;

            // Right after "<join> "
            if (position == length) {

                // Only add some JOIN identifiers if the actual identifier is shorter or incomplete
                if (identifier == LEFT) {
                    addIdentifier(LEFT_JOIN);
                    addIdentifier(LEFT_OUTER_JOIN);

                    if (isJoinFetchIdentifiable() ||
                        !expression.hasAs() && !expression.hasIdentificationVariable()) {

                        addIdentifier(LEFT_JOIN_FETCH);
                        addIdentifier(LEFT_OUTER_JOIN_FETCH);
                    }
                }
                else if (identifier == INNER) {
                    addIdentifier(INNER_JOIN);

                    if (isJoinFetchIdentifiable() ||
                        !expression.hasAs() && !expression.hasIdentificationVariable()) {

                        addIdentifier(INNER_JOIN_FETCH);
                    }
                }
                else if (identifier.equals("LEFT_OUTER")) {
                    addIdentifier(LEFT_OUTER_JOIN);

                    if (isJoinFetchIdentifiable() ||
                        !expression.hasAs() && !expression.hasIdentificationVariable()) {

                        addIdentifier(LEFT_OUTER_JOIN_FETCH);
                    }
                }
                else {
                    addLeftIdentificationVariables(expression);
                }
            }

            // After "join association path expression "
            if (expression.hasJoinAssociationPath() &&
                expression.hasSpaceAfterJoinAssociation()) {

                length += expression.getJoinAssociationPath().getLength() + SPACE_LENGTH;

                // Right after "join association path expression "
                // Make sure to verify if AS can be added if it's a JOIN FETCH expression
                if (!joinFetch || joinFetch && isJoinFetchIdentifiable()) {

                    if (isPositionWithin(position, length, AS)) {
                        addIdentifier(AS);
                    }

                    if (expression.hasAs()) {
                        length += 2;

                        if (expression.hasSpaceAfterAs()) {
                            length++;
                        }
                    }
                }

                if (joinFetch || expression.hasIdentificationVariable()) {

                    length += expression.getIdentificationVariable().getLength();

                    if (expression.hasSpaceAfterIdentificationVariable()) {
                        length += SPACE_LENGTH;
                    }

                    // After "join association path expression [AS] identification variable"
                    if (position == length) {
                        addIdentifier(ON);
                    }
                }
            }
        }
    }

    @Override
    public void visit(JPQLExpression expression) {

        int position = queryPosition.getPosition(expression) - corrections.peek();

        // At the beginning of the query
        if (position == 0) {
            addIdentifier(DELETE_FROM);
            addIdentifier(SELECT);
            addIdentifier(UPDATE);
        }
    }

    @Override
    public void visit(KeyExpression expression) {
        super.visit(expression);
        visitSingleEncapsulatedExpression(expression, IdentificationVariableType.LEFT_COLLECTION);
    }

    @Override
    public void visit(KeywordExpression expression) {
        super.visit(expression);

        int position = queryPosition.getPosition(expression) - corrections.peek();
        String keyword = expression.getText();

        // Within the identifier
        if ((keyword == TRUE)  && isPositionWithin(position, TRUE)  ||
            (keyword == FALSE) && isPositionWithin(position, FALSE) ||
            (keyword == NULL)  && isPositionWithin(position, NULL)) {

            proposals.addIdentifier(TRUE);
            proposals.addIdentifier(FALSE);
            proposals.addIdentifier(NULL);

            addIdentificationVariables();
            addFunctionIdentifiers(expression.getParent().findQueryBNF(expression));
        }
    }

    @Override
    public void visit(LengthExpression expression) {
        super.visit(expression);
        visitSingleEncapsulatedExpression(expression, IdentificationVariableType.ALL);
    }

    @Override
    public void visit(LikeExpression expression) {
        super.visit(expression);
        int position = queryPosition.getPosition(expression) - corrections.peek();

        if (expression.hasStringExpression()) {
            int length = expression.getStringExpression().getLength() + SPACE_LENGTH;

            // Within "LIKE" or "NOT LIKE"
            if (isPositionWithin(position, length, expression.getIdentifier())) {
                proposals.addIdentifier(LIKE);
                proposals.addIdentifier(NOT_LIKE);
            }
            // After "LIKE " or "NOT LIKE "
            else if (expression.hasSpaceAfterLike()) {
                length += expression.getIdentifier().length() + SPACE_LENGTH;

                // After "<pattern value> "
                if (expression.hasPatternValue() &&
                    expression.hasSpaceAfterPatternValue()) {

                    length += expression.getPatternValue().getLength() + SPACE_LENGTH;

                    // Within "ESCAPE"
                    if (isPositionWithin(position, length, ESCAPE)) {
                        proposals.addIdentifier(ESCAPE);
                    }
                }
            }
        }
    }

    @Override
    public void visit(LocateExpression expression) {
        super.visit(expression);
        visitCollectionExpression(expression, LOCATE, getTripleEncapsulatedCollectionHelper());
    }

    @Override
    public void visit(LowerExpression expression) {
        super.visit(expression);
        visitSingleEncapsulatedExpression(expression, IdentificationVariableType.ALL);
    }

    @Override
    public void visit(MaxFunction expression) {
        super.visit(expression);
        visitAggregateFunction(expression);
    }

    @Override
    public void visit(MinFunction expression) {
        super.visit(expression);
        visitAggregateFunction(expression);
    }

    @Override
    public void visit(ModExpression expression) {
        super.visit(expression);
        visitCollectionExpression(expression, MOD, getDoubleEncapsulatedCollectionHelper());
    }

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

    @Override
    public void visit(NotExpression expression) {
        super.visit(expression);
        int position = queryPosition.getPosition(expression) - corrections.peek();

        // Within "NOT"
        if (isPositionWithin(position, NOT)) {
            proposals.addIdentifier(NOT);
        }
    }

    @Override
    public void visit(NullComparisonExpression expression) {
        super.visit(expression);
        int position = queryPosition.getPosition(expression) - corrections.peek();
        int length = 0;

        if (expression.hasExpression()) {
            length += expression.getExpression().getLength() + SPACE_LENGTH;
        }

        // Within "IS NULL" or "IS NOT NULL"
        if (isPositionWithin(position, length, expression.getIdentifier())) {
            proposals.addIdentifier(IS_NULL);
            proposals.addIdentifier(IS_NOT_NULL);
        }
    }

    @Override
    public void visit(NullExpression expression) {
        // No content assist can be provider
        super.visit(expression);
    }

    @Override
    public void visit(NullIfExpression expression) {
        super.visit(expression);
        visitCollectionExpression(expression, NULLIF, getDoubleEncapsulatedCollectionHelper());
    }

    @Override
    public void visit(NumericLiteral expression) {
        // No content assist can be provider for a numerical value
        super.visit(expression);
    }

    @Override
    public void visit(ObjectExpression expression) {
        super.visit(expression);
        visitSingleEncapsulatedExpression(expression, IdentificationVariableType.ALL);
    }

    @Override
    public void visit(OnClause expression) {
        if (!isLocked(expression)) {
            super.visit(expression);
            visitCollectionExpression(expression, expression.getIdentifier(), getConditionalClauseCollectionHelper());
        }
    }

    @Override
    public void visit(OrderByClause expression) {
        if (!isLocked(expression)) {
            super.visit(expression);
            visitCollectionExpression(expression, ORDER_BY, getOrderByClauseCollectionHelper());
        }
    }

    @Override
    public void visit(OrderByItem expression) {
        super.visit(expression);
        int position = queryPosition.getPosition(expression) - corrections.peek();

        // After the order by item
        if (expression.hasExpression()) {
            int length = expression.getExpression().getLength();

            // Within the expression
            if ((position > -1) && (position <= length)) {

                if (!expression.hasNulls() &&
                    !expression.hasOrdering()) {

                    addIdentifier(ASC);
                    addIdentifier(DESC);
                }
            }
            // After the expression
            else if (expression.hasSpaceAfterExpression()) {
                length++;

                // Right before "ASC" or "DESC"
                if (position == length) {
                    proposals.addIdentifier(ASC);
                    proposals.addIdentifier(DESC);
                }
                else {
                    // Right after the space
                    Ordering ordering = expression.getOrdering();

                    // Within "ASC" or "DESC"
                    if ((ordering != Ordering.DEFAULT) &&
                        isPositionWithin(position, length, ordering.name())) {

                        proposals.addIdentifier(ASC);
                        proposals.addIdentifier(DESC);
                    }
                }
            }
        }
    }

    @Override
    public void visit(OrExpression expression) {
        super.visit(expression);
        visitLogicalExpression(expression);
    }

    @Override
    public void visit(RangeVariableDeclaration expression) {
        super.visit(expression);
        int position = queryPosition.getPosition(expression) - corrections.peek();

        // After "<abstract schema name> "
        if (expression.hasRootObject()) {
            int length = expression.getRootObject().getLength();

            // After "<abstract schema name> "
            if (expression.hasSpaceAfterRootObject()) {
                length++;

                // Right after "<abstract schema name> "
                if (position == length) {
                    addIdentifier(AS);
                }
                // Within 'AS'
                else if (expression.hasAs() && isPositionWithin(position, length, AS)) {
                    addIdentifier(AS);
                }
            }
        }
    }

    @Override
    public void visit(ResultVariable expression) {
        super.visit(expression);
        int position = queryPosition.getPosition(expression) - corrections.peek();

        if (expression.hasSelectExpression()) {
            Expression selectItem = expression.getSelectExpression();
            int length = selectItem.getLength() + SPACE_LENGTH;

            // Right before "AS"
            if (position == length) {

                if (isComplete(selectItem)) {
                    addIdentifier(AS);
                }

                if (areArithmeticSymbolsAppendable(selectItem)) {
                    addArithmeticIdentifiers();
                }
            }
            // Within "AS"
            else if (expression.hasAs() && isPositionWithin(position, length, AS)) {

                if (isComplete(selectItem)) {
                    addIdentifier(AS);
                }

                addFunctionIdentifiers(selectItem);
            }
        }
        // Now add other functions as well, example " A|S e" could become "AVG e"
        else if (expression.hasAs() && isPositionWithin(position, AS)) {
            addFunctionIdentifiers(expression);
        }
    }

    @Override
    public void visit(SelectClause expression) {
        if (!isLocked(expression)) {
            super.visit(expression);
            visitCollectionExpression(expression, SELECT, getSelectClauseCollectionHelper());
        }
    }

    @Override
    public void visit(SelectStatement expression) {
        if (!isLocked(expression)) {
            super.visit(expression);
            visitStatement(expression, getSelectClauseStatementHelper());
        }
    }

    @Override
    public void visit(SimpleFromClause expression) {
        if (!isLocked(expression)) {
            super.visit(expression);
            visitCollectionExpression(expression, FROM, getFromClauseCollectionHelper());
        }
    }

    @Override
    public void visit(SimpleSelectClause expression) {
        if (!isLocked(expression)) {
            super.visit(expression);
            visitCollectionExpression(expression, SELECT, getSimpleSelectClauseCollectionHelper());
        }
    }

    @Override
    public void visit(SimpleSelectStatement expression) {
        if (!isLocked(expression)) {
            // Don't continue traversing the parent hierarchy because a subquery
            // will handle all the possible proposals
            visitStatement(expression, getSimpleSelectClauseStatementHelper());
        }
    }

    @Override
    public void visit(SizeExpression expression) {
        super.visit(expression);
        visitSingleEncapsulatedExpression(expression, IdentificationVariableType.ALL);
    }

    @Override
    public void visit(SqrtExpression expression) {
        expression.accept(getVisitParentVisitor());
        visitSingleEncapsulatedExpression(expression, IdentificationVariableType.ALL);
    }

    @Override
    public void visit(StateFieldPathExpression expression) {
        super.visit(expression);
        if (!isFollowingInvalidExpression(expression)) {
            visitPathExpression(expression);
        }
    }

    @Override
    public void visit(StringLiteral expression) {
        // No content assist required
        super.visit(expression);
    }

    @Override
    public void visit(SubExpression expression) {
        super.visit(expression);
        int position = queryPosition.getPosition(expression) - corrections.peek();

        if (position == 1) {
            addFunctionIdentifiers(expression);
        }
    }

    @Override
    public void visit(SubstringExpression expression) {
        super.visit(expression);
        visitCollectionExpression(expression, SUBSTRING, getTripleEncapsulatedCollectionHelper());
    }

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

    @Override
    public void visit(SumFunction expression) {
        super.visit(expression);
        visitAggregateFunction(expression);
    }

    @Override
    public void visit(TreatExpression expression) {
        super.visit(expression);
        int position = queryPosition.getPosition(expression) - corrections.peek();

        // Within "TREAT"
        if (isPositionWithin(position, TREAT)) {
            addIdentifier(TREAT);
            addIdentificationVariables();
            addFunctionIdentifiers(expression.getParent().findQueryBNF(expression));
        }
        // After "TREAT("
        else if (expression.hasLeftParenthesis()) {
            int length = TREAT.length() + 1;

            // Right after "TREAT("
            if (position == length) {
                addLeftIdentificationVariables(expression);
            }

            // After "<collection-valued path expression> "
            if (expression.hasCollectionValuedPathExpression() &&
                expression.hasSpaceAfterCollectionValuedPathExpression()) {

                Expression collectionValuedPathExpression = expression.getCollectionValuedPathExpression();
                length += collectionValuedPathExpression.getLength() + SPACE_LENGTH;

                // Within "AS"
                if (isPositionWithin(position, length, AS)) {
                    addIdentifier(AS);

                    // If the entity type is not specified, then we can add
                    // the possible abstract schema names
                    if (!expression.hasEntityType()) {

                        // If the type of the path expression is resolvable,
                        // then filter the abstract schema types
                        IType type = queryContext.getType(collectionValuedPathExpression);

                        if (type.isResolvable()) {
                            addEntities(type);
                        }
                        else {
                            addEntities();
                        }
                    }
                }
            }

            // After "AS "
            if (expression.hasAs() &&
                expression.hasSpaceAfterAs()) {

                length += AS.length() + SPACE_LENGTH;

                // Right after "AS "
                if (position == length) {
                    // If the type of the path expression is resolvable,
                    // then filter the abstract schema types
                    IType type = queryContext.getType(expression.getCollectionValuedPathExpression());

                    if (type.isResolvable()) {
                        addEntities(type);
                    }
                    else {
                        addEntities();
                    }
                }
            }
        }
    }

    @Override
    public void visit(TrimExpression expression) {
        super.visit(expression);
        int position = queryPosition.getPosition(expression) - corrections.peek();
        int length = 0;

        // Within "TRIM"
        if (isPositionWithin(position, TRIM)) {
            addIdentifier(TRIM);
            addIdentificationVariables();
            addFunctionIdentifiers(expression.getParent().findQueryBNF(expression));
        }
        // After "TRIM("
        else if (expression.hasLeftParenthesis()) {
            length += TRIM.length() + 1;

            // Right after "TRIM("
            if (position == length) {
                addIdentifier(BOTH);
                addIdentifier(LEADING);
                addIdentifier(TRAILING);

                if (!expression.hasTrimCharacter() &&
                    !expression.hasFrom()) {

                    addIdentificationVariables();
                    addFunctionIdentifiers(StringPrimaryBNF.ID);
                }
            }

            // Within the trim specification
            if (expression.hasSpecification()) {
                String specification = expression.getSpecification().name();

                if (isPositionWithin(position, length, specification)) {
                    addIdentifier(BOTH);
                    addIdentifier(LEADING);
                    addIdentifier(TRAILING);

                    if (!expression.hasTrimCharacter() &&
                        !expression.hasFrom()) {

                        addIdentificationVariables();
                        addFunctionIdentifiers(StringPrimaryBNF.ID);
                    }
                }

                length += specification.length();
            }

            if (expression.hasSpaceAfterSpecification()) {
                length += SPACE_LENGTH;
            }

            // Trim character
            if (expression.hasTrimCharacter()) {
                length += expression.getTrimCharacter().getLength();
            }

            if (expression.hasSpaceAfterTrimCharacter()) {
                length += SPACE_LENGTH;
            }

            // Right after "<trim_character> "
            if (position == length) {
                addIdentifier(FROM);

                if (!expression.hasFrom()) {
                    addIdentificationVariables();
                    addFunctionIdentifiers(StringPrimaryBNF.ID);
                }
            }

            if (expression.hasFrom()) {

                // Within "FROM"
                if (isPositionWithin(position, length, FROM)) {
                    addIdentifier(FROM);
                }

                length += FROM.length();
            }

            if (expression.hasSpaceAfterFrom()) {
                length += SPACE_LENGTH;
            }

            // Right after "FROM "
            if (position == length) {
                addIdentificationVariables();
                addFunctionIdentifiers(StringPrimaryBNF.ID);
            }

            // Right after the string literal but there is no trim character,
            // nor FROM and there is a virtual space
            if (expression.hasExpression()) {
                length += expression.getExpression().getLength();

                if ((position == length + virtualSpaces.peek()) &&
                    !expression.hasTrimCharacter() &&
                    !expression.hasFrom()) {

                    addIdentifier(FROM);
                }
            }
        }
    }

    @Override
    public void visit(TypeExpression expression) {
        super.visit(expression);
        visitSingleEncapsulatedExpression(expression, IdentificationVariableType.ALL);
    }

    @Override
    public void visit(UnknownExpression expression) {
        super.visit(expression);
        visitInvalidExpression(expression);
    }

    @Override
    public void visit(UpdateClause expression) {
        super.visit(expression);
        int position = queryPosition.getPosition(expression) - corrections.peek();

        // Within "UPDATE"
        if (isPositionWithin(position, UPDATE)) {
            proposals.addIdentifier(UPDATE);
        }
        // After "UPDATE "
        else if (expression.hasSpaceAfterUpdate()) {
            int length = UPDATE.length() + SPACE_LENGTH;

            // Right after "UPDATE "
            if (position == length) {
                addEntities();
            }
            // After "<range variable declaration> "
            else if (expression.hasRangeVariableDeclaration()) {

                RangeVariableDeclaration rangeVariableDeclaration = findRangeVariableDeclaration(expression);

                if ((rangeVariableDeclaration != null) &&
                     rangeVariableDeclaration.hasRootObject() &&
                     rangeVariableDeclaration.hasSpaceAfterRootObject()) {

                    length += rangeVariableDeclaration.getRootObject().getLength() + SPACE_LENGTH;

                    // Example: "UPDATE System s"
                    if (!expression.hasSet()        &&
                        !rangeVariableDeclaration.hasAs() &&
                        isPositionWithin(position, length, SET)) {

                        addIdentifier(SET);
                    }
                    // Example: "UPDATE System s "
                    // Example: "UPDATE System AS s "
                    else {

                        if (rangeVariableDeclaration.hasAs()) {
                            length += 2;
                        }

                        if (rangeVariableDeclaration.hasSpaceAfterAs()) {
                            length++;
                        }

                        if (rangeVariableDeclaration.hasIdentificationVariable()) {
                            length += rangeVariableDeclaration.getIdentificationVariable().getLength();
                        }

                        if (expression.hasSpaceAfterRangeVariableDeclaration()) {
                            length++;
                        }

                        // Within "SET"
                        if ((rangeVariableDeclaration.hasAs() && rangeVariableDeclaration.hasIdentificationVariable() ||
                            !rangeVariableDeclaration.hasAs() && rangeVariableDeclaration.hasIdentificationVariable()) &&
                            isPositionWithin(position, length, SET)) {

                            addIdentifier(SET);
                        }
                        // After "SET "
                        else if (expression.hasSet() &&
                                 expression.hasSpaceAfterSet()) {

                            length += SET.length() + SPACE_LENGTH;

                            // Right after "SET "
                            if (position == length) {
                                addIdentificationVariables();
                            }
                            // Within the new value expressions
                            else {
                                visitCollectionExpression(expression, ExpressionTools.EMPTY_STRING, getUpdateItemCollectionHelper());
                            }
                        }
                    }
                }
            }
        }
    }

    @Override
    public void visit(UpdateItem expression) {
        super.visit(expression);
        int position = queryPosition.getPosition(expression) - corrections.peek();
        int length = 0;

        // At the beginning
        if (position == length) {
            addIdentificationVariables();
        }
        else if (expression.hasStateFieldPathExpression() &&
                 expression.hasSpaceAfterStateFieldPathExpression()) {

            length += expression.getStateFieldPathExpression().getLength() + SPACE_LENGTH;

            // Within "="
            if (position == length) {
                proposals.addIdentifier(EQUAL);
            }
            // After "="
            else if (expression.hasEqualSign()) {
                length++;

                // Right after "="
                if (position == length) {
                    proposals.addIdentifier(EQUAL);
                    addIdentificationVariables();
                    addFunctionIdentifiers(NewValueBNF.ID);
                }
                else if (expression.hasSpaceAfterEqualSign()) {
                    length++;

                    // Right after "= "
                    if (position == length) {
                        addIdentificationVariables();
                        addFunctionIdentifiers(NewValueBNF.ID);
                    }
                }
            }
        }
    }

    @Override
    public void visit(UpdateStatement expression) {
        if (!isLocked(expression)) {
            super.visit(expression);
            visitStatement(expression, getUpdateClauseStatementHelper());
        }
    }

    @Override
    public void visit(UpperExpression expression) {
        super.visit(expression);
        visitSingleEncapsulatedExpression(expression, IdentificationVariableType.ALL);
    }

    @Override
    public void visit(ValueExpression expression) {
        super.visit(expression);
        visitSingleEncapsulatedExpression(expression, IdentificationVariableType.LEFT_COLLECTION);
    }

    @Override
    public void visit(WhenClause expression) {
        super.visit(expression);
        int position = queryPosition.getPosition(expression) - corrections.peek();

        // Within "WHEN"
        if (isPositionWithin(position, WHEN)) {
            if (!isWithinInvalidExpression(expression)) {
                proposals.addIdentifier(WHEN);
            }
        }
        // After "WHEN "
        else if (expression.hasSpaceAfterWhen()) {
            int length = 5 /* WHEN + space */;

            // Right after "WHEN "
            if (position == length) {
                visitCollectionExpression(expression, WHEN, getWhenClauseConditionalClauseCollectionHelper());
            }
            else {
                length += expression.getWhenExpression().getLength();

                // After "WHEN <expression> " => THEN
                if (expression.hasSpaceAfterWhenExpression()) {
                    length++;

                    // Right after "WHEN <expression> " => THEN
                    if (position == length) {

                        // Check an incomplete WHEN expression
                        visitCollectionExpression(expression, WHEN, getWhenClauseConditionalClauseCollectionHelper());

                        // If the expression is complete, then "THEN" is a valid proposal
                        if (isComplete(expression)) {
                            proposals.addIdentifier(THEN);
                        }
                    }
                    else if (expression.hasThen()) {

                        // Within "THEN"
                        if (isPositionWithin(position, length, THEN)) {
                            proposals.addIdentifier(THEN);
                        }
                        else {
                            length += 4 /* THEN */;

                            // After "WHEN <expression> THEN "
                            if (expression.hasSpaceAfterThen()) {
                                length++;

                                // Right after "WHEN <expression> THEN "
                                if (position == length) {
                                    addIdentificationVariables();
                                    addFunctionIdentifiers(ScalarExpressionBNF.ID);
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    @Override
    public void visit(WhereClause expression) {
        if (!isLocked(expression)) {
            super.visit(expression);
            visitCollectionExpression(expression, expression.getIdentifier(), getConditionalClauseCollectionHelper());
        }
    }

    /**
     * Visits the given {@link AggregateFunction} and attempts to find valid proposals.
     *
     * @param expression The {@link AggregateFunction} to inspect
     */
    protected void visitAggregateFunction(AggregateFunction expression) {

        if (isFollowingInvalidExpression(expression)) {
            return;
        }

        int position = queryPosition.getPosition(expression) - corrections.peek();
        String identifier = expression.getIdentifier();

        // Within "<identifier>"
        if (isPositionWithin(position, identifier)) {
            addIdentifier(identifier);
            addFunctionIdentifiers(expression);
        }
        // After "<identifier>("
        else if (expression.hasLeftParenthesis()) {
            int length = identifier.length() + 1 /* '(' */;
            boolean hasDistinct = expression.hasDistinct();

            // Within "DISTINCT"
            if (hasDistinct && isPositionWithin(position, length, DISTINCT) ) {
                addIdentifier(DISTINCT);
            }
            // After "("
            else {
                if (hasDistinct && expression.hasSpaceAfterDistinct()) {
                    length += DISTINCT.length() + SPACE_LENGTH;
                }

                // Right after "(" or right after "(DISTINCT "
                if (position == length) {
                    if (!hasDistinct) {
                        addIdentifier(DISTINCT);
                    }
                    addIdentificationVariables();
                    addFunctionIdentifiers(expression.getEncapsulatedExpressionQueryBNFId());
                }
            }
        }
    }

    /**
     * Visits the given {@link ArithmeticExpression} and attempts to find valid proposals.
     *
     * @param expression The {@link ArithmeticExpression} to inspect
     */
    protected void visitArithmeticExpression(ArithmeticExpression expression) {

        int position = queryPosition.getPosition(expression) - corrections.peek();
        int length = 0;

        if (expression.hasLeftExpression()) {
            length += expression.getLeftExpression().getLength() + SPACE_LENGTH;
        }

        // Within the arithmetic sign
        if (isPositionWithin(position, length, PLUS)) {
            addAggregateIdentifiers(expression.getQueryBNF());
        }
        // After the arithmetic sign, with or without the space
        else if (expression.hasSpaceAfterIdentifier()) {
            length += 2;

            // Right after the space
            if (position == length) {
                addIdentificationVariables();
                addFunctionIdentifiers(expression.getRightExpressionQueryBNFId());
            }
        }
    }

    /**
     * Adds the possible proposals for the given {@link Expression expression} based on the location of
     * the cursor and the content of the expression.
     *
     * @param expression The {@link Expression expression} being visited
     * @param identifier The JPQL identifier of the {@link Expression} being visited, if the {@link
     * Expression} does not have an identifier, than an empty string should be passed
     * @param helper This helper completes the behavior of this method by retrieving the information
     * from the given {@link Expression}
     */
    protected <T extends Expression> void visitCollectionExpression(T expression,
                                                                    String identifier,
                                                                    CollectionExpressionHelper<T> helper) {

        if (isFollowingInvalidExpression(expression)) {
            return;
        }

        int position = queryPosition.getPosition(expression) - corrections.peek();
        boolean hasIdentifier = (identifier.length() > 0);
        boolean virtualSpace = hasVirtualSpace();

        // Within the identifier
        if (hasIdentifier && isPositionWithin(position, identifier)) {
            helper.addIdentifier(expression, identifier);
        }
        // After "<identifier>(" or "<identifier> "
        else if (helper.hasDelimiterAfterIdentifier(expression)) {
            int length = !hasIdentifier ? 0 : identifier.length() + 1 /* delimiter, either space or ( */;
            length += helper.preExpressionLength(expression);

            // Right after "<identifier>(" or "<identifier> "
            if (position == length) {
                helper.addTheBeginningOfChild(expression, null, 0, false);
            }
            // Within the encapsulated expressions
            else {

                // Create a collection representation of the encapsulated expression(s)
                CollectionExpression collectionExpression = helper.buildCollectionExpression(expression);
                boolean hasComma = false;
                boolean previousHasComma = false;

                // Determine the maximum children count, it is possible the query contains more children
                // than the expession's grammar would actually allow. The content assist will only
                // provide assistance from the first child to the last allowed child
                int childrenCount = collectionExpression.childrenSize();
                int count = Math.min(childrenCount, helper.maxCollectionSize(expression));

                // Iterate through each child of the collection
                for (int index = 0; index < count; index++) {

                    Expression child = collectionExpression.getChild(index);
                    int childLength = 0;

                    // At the beginning of the child
                    if (position == length) {
                        helper.addTheBeginningOfChild(expression, collectionExpression, index, hasComma);
                        break;
                    }
                    // Each expression within the collection has to be separated by a comma, the previous
                    // expression and the expression at the current index are not separated by a comma
                    // Example: "SELECT e FROM Employee e GROUP" <- [ "Employee e", "GROUP" ]
                    else if ((index > 0) && !hasComma) {

                        length += child.getLength();

                        // At the end of the child
                        if (position == length) {
                            helper.addAtTheEndOfChild(expression, collectionExpression, index, hasComma, false);
                            break;
                        }

                        // To be valid, each child has to be separated by a comma,
                        // ask the helper if it should continue with the next child
                        if (!helper.canContinue(expression, collectionExpression, index)) {
                            break;
                        }
                        // Special case when reaching the end of the collection
                        else if (index + 1 == count) {
                            helper.addAtTheEndOfChild(expression, collectionExpression, index, hasComma, false);
                        }
                    }
                    else {
                        childLength = child.getLength();

                        // At the end of the child
                        if ((position == length + childLength) ||
                            (virtualSpace && (position == length + childLength + SPACE_LENGTH))) {

                            helper.addAtTheEndOfChild(expression, collectionExpression, index, hasComma, virtualSpace);
                            break;
                        }
                    }

                    // Now add the child's length and length used by the comma and space
                    length += childLength;

                    // Move after the comma
                    previousHasComma = hasComma;
                    hasComma = collectionExpression.hasComma(index);

                    if (hasComma) {

                        // Two items were not separated by a comma and the next one is, this is invalid
                        if ((index > 0) && !previousHasComma) {
                            return;
                        }

                        length++;

                        // After the comma, add the proposals
                        if (position == length) {
                            helper.addTheBeginningOfChild(expression, collectionExpression, index + 1, hasComma);
                            break;
                        }
                    }

                    // Move after the space that follows the comma
                    if (collectionExpression.hasSpace(index)) {
                        length++;

                        // At the end of the child
                        if (!hasComma && (position == length)) {
                            helper.addAtTheEndOfChild(expression, collectionExpression, index, hasComma, true);
                        }
                    }

                    // Nothing more can be looked at
                    if (position < length) {
                        break;
                    }
                }
            }
        }
    }

    protected void visitEndingExpression(Expression expression) {

        // Keep track of the original QueryPosition, the new one will differ
        // to properly accommodate for the invalid portion of the query
        QueryPosition oldQueryPosition = queryPosition;

        //
        // Step 1
        //
        // Create a new QueryPosition for which the positions is set to be at the end
        // of the valid fragment of the JPQL query, which is up to right before the
        // beginning of the invalid fragment
        // Example: "SELECT e FROM Employee e S| WHERE e.name = 'JPQL'" <- | is the position of the cursor
        //          Valid fragment: "SELECT e FROM Employee e "
        //          Invalid fragment: "S WHERE e.name = 'JPQL'"
        queryPosition = buildEndingPositionFromInvalidExpression(expression, expression, new boolean[1]);

        // Adjust the position to include the whitespace owned by the parent expression
        expression = queryPosition.getExpression();

        while (expression != null) {

            int position = queryPosition.getPosition(expression);

            if (position == -1) {
                expression = null;
            }
            else {
                queryPosition.addPosition(expression, position + 1);
                expression = expression.getParent();
            }
        }

        //
        // Step 2
        //
        // Now make sure the correction is reset temporarily
        corrections.add(0);
        addVirtualSpace();

        // Now traverse the tree starting at the leaf from the valid fragment
        queryPosition.getExpression().accept(this);

        // Revert the data
        queryPosition = oldQueryPosition;
        corrections.pop();
        removeVirtualSpace();
    }

    protected void visitEnumConstant(AbstractPathExpression expression) {

        int position = queryPosition.getPosition(expression);
        String text = expression.toActualText();
        int lastDotIndex = text.lastIndexOf(DOT);

        // Check to see if an enum constant can be used at the expression's location
        if (isEnumAllowed(expression)) {
            boolean enumConstant = false;

            // The position is after the last dot, check for enum constants
            if (position > lastDotIndex) {

                // Retrieve the enum type if the path up to the last dot is a fully qualified enum type
                String enumType = expression.toParsedText().substring(0, lastDotIndex);
                IType type = queryContext.getType(enumType);

                // The path expression before the last dot is an enum type
                if (type.isResolvable() && type.isEnum()) {
                    enumConstant = true;

                    // Now retrieve the portion of the enum constant based on the cursor position
                    String word = text.substring(lastDotIndex + 1, position);

                    // Add the enum constants and filter them based on what's already proposed
                    addEnumConstants(type, word);
                }
            }

            // Enum type
            if (!enumConstant) {

                // Now retrieve the portion of the enum constant based on the cursor position
                text = text.substring(0, position);

                // Set the possible starting of a fully qualified enum type
                proposals.setClassNamePrefix(text, ClassType.ENUM);
            }
        }
    }

    protected void visitInvalidExpression(Expression expression) {

        if (!isLocked(expression)) {
            int position = queryPosition.getPosition(expression) - corrections.peek();
            boolean virtualSpace = (position == 1) && (word.length() == 0);

            // 1. Within the first word of the invalid fragment
            // 2. Or after the ending whitespace
            // Otherwise no need to do anything if beyond it
            if (isPositionWithin(position, word) || virtualSpace) {

                lockedExpressions.add(expression);

                // Keep track of the original QueryPosition, the new one will differ
                // to properly accommodate for the invalid portion of the query
                QueryPosition oldQueryPosition = queryPosition;

                boolean[] spaces = { false };

                //
                // Step 1
                //
                // Create a new QueryPosition for which the positions is set to be at the end
                // of the valid fragment of the JPQL query, which is up to right before the
                // beginning of the invalid fragment
                // Example: "SELECT e FROM Employee e S| WHERE e.name = 'JPQL'" <- | is the position of the cursor
                //          Valid fragment: "SELECT e FROM Employee e "
                //          Invalid fragment: "S WHERE e.name = 'JPQL'"
                queryPosition = buildEndingPositionFromInvalidExpression(expression, expression.getRoot(), spaces);

                //
                // Step 2
                //
                // Now make sure the correction is reset temporarily
                corrections.add(0);

                // This means the valid fragment ends with a whitespace, keep track of it
                if (spaces[0] || virtualSpace) {
                    addVirtualSpace();
                }

                // Now traverse the tree starting at the leaf from the valid fragment
                queryPosition.getExpression().accept(this);

                // Revert the data
                queryPosition = oldQueryPosition;
                corrections.pop();
                lockedExpressions.pop();

                if (spaces[0] || virtualSpace) {
                    removeVirtualSpace();
                }
            }
        }
    }

    /**
     * Visits the given {@link LogicalExpression} and attempts to find valid proposals.
     *
     * @param expression The {@link LogicalExpression} to inspect
     */
    protected void visitLogicalExpression(LogicalExpression expression) {

        if (isFollowingInvalidExpression(expression)) {
            return;
        }

        int position = queryPosition.getPosition(expression) - corrections.peek();
        String identifier = expression.getIdentifier();
        int length = 0;

        if (expression.hasLeftExpression()) {
            length += expression.getLeftExpression().getLength() + SPACE_LENGTH;
        }

        // Within "AND" or "OR"
        if (isPositionWithin(position, length, identifier)) {
            proposals.addIdentifier(identifier);
        }
        // After "AND " or "OR "
        else if (expression.hasSpaceAfterIdentifier()) {
            length += identifier.length() + SPACE_LENGTH;

            // Right after "AND " or "OR "
            if (position == length) {
                addIdentificationVariables();
                addFunctionIdentifiers(expression.getRightExpressionQueryBNFId());
            }
        }
    }

    /**
     * Visits the given {@link AbstractPathExpression} and attempts to find valid proposals.
     * <p>
     * Note: A path expression can represent many things: state field, relationship field, collection
     * field, enum constant, etc. This will consider all variations.
     *
     * @param expression The {@link AbstractPathExpression} to inspect
     */
    protected void visitPathExpression(AbstractPathExpression expression) {

        int position = queryPosition.getPosition(expression);
        String text = expression.toActualText();
        int dotIndex = text.indexOf(DOT);

        if (position > -1) {

            String variableName = queryContext.literal(
                expression.getIdentificationVariable(),
                LiteralType.IDENTIFICATION_VARIABLE
            );

            boolean variable = ExpressionTools.stringIsNotEmpty(variableName);

            // The position if after the identification variable
            if ((dotIndex > -1) && (position > dotIndex)) {

                // Retrieve the filter based on the location of the state field path, for instance, in
                // a JOIN or IN expression, the filter has to filter out the property and accept the
                // fields of collection type
                visitPathExpression(expression, buildMappingFilter(expression));

                // Don't do anything if the first path is not an identification variable,
                // which means it's either KEY() or VALUE()
                if (variable) {

                    // Attempts to resolve a possible fully qualified enum constant
                    visitEnumConstant(expression);

                    // Attempts to resolve third party option
                    visitThirdPartyPathExpression(expression, variableName);
                }
            }
            // The position is within the identification variable but don't do anything if the
            // identification variable is either KEY() or VALUE()
            else if (variable) {
                corrections.add(queryPosition.getPosition(expression));
                visit(expression);
                corrections.pop();
            }
        }
    }

    /**
     * Visits the given {@link AbstractPathExpression} by attempting to resolve the path.
     *
     * @param expression The {@link AbstractPathExpression} to inspect
     * @param filter The {@link Filter} is used to filter out {@link IMapping} that are not valid
     * based on their type and the type that is allowed
     */
    protected void visitPathExpression(AbstractPathExpression expression, Filter<IMapping> filter) {

        MappingCollector mappingCollector = getDefaultMappingCollector();
        int position = queryPosition.getPosition(expression);
        boolean mappingCollectorCreated = false;
        Resolver resolver = null;
        int length = 0;

        for (int index = 0, count = expression.pathSize(); index < count; index++) {
            String path = expression.getPath(index);

            // We're at the position, create the ChoiceBuilder
            if (position <= length + path.length()) {

                if (length == position) {
                    path = ExpressionTools.EMPTY_STRING;
                }
                else if (position - length > -1) {
                    path = path.substring(0, position - length);
                }

                // Special case where the path expression only has the
                // identification variable set
                if (resolver == null) {
                    break;
                }

                mappingCollector = buildFilteringMappingCollector(expression, resolver, filter, path);
                mappingCollectorCreated = true;
                break;
            }
            // The path is entirely before the position of the cursor
            else {
                // The first path is always an identification variable
                if (resolver == null) {
                    resolver = queryContext.getResolver(expression.getIdentificationVariable());
                }
                // Any other path is a property or collection-valued path
                else if ((index + 1 < count) || expression.endsWithDot()) {
                    Resolver childResolver = resolver.getChild(path);
                    if (childResolver == null) {
                        childResolver = new StateFieldResolver(resolver, path);
                        resolver.addChild(path, childResolver);
                        resolver = childResolver;
                    }
                }

                // Move the cursor after the path and dot
                length += path.length() + 1;
            }
        }

        if (!mappingCollectorCreated && (resolver != null)) {
            mappingCollector = buildMappingCollector(expression, resolver, filter);
        }

        proposals.addMappings(mappingCollector.buildProposals());
    }

    /**
     * Adds the possible proposals for the given {@link AbstractSingleEncapsulatedExpression expression}
     * based on the location of the cursor and the content of the expression.
     *
     * @param expression The {@link AbstractSingleEncapsulatedExpression expression} being visited
     * @param identificationVariableType The type of identification variables that can be added as
     * possible proposals
     */
    protected void visitSingleEncapsulatedExpression(AbstractSingleEncapsulatedExpression expression,
                                                     IdentificationVariableType identificationVariableType) {

        visitSingleEncapsulatedExpression(
            expression,
            identificationVariableType,
            expression.getIdentifier()
        );
    }

    /**
     * Adds the possible proposals for the given {@link AbstractSingleEncapsulatedExpression expression}
     * based on the location of the cursor and the content of the expression.
     *
     * @param expression The {@link AbstractSingleEncapsulatedExpression expression} being visited
     * @param identificationVariableType The type of identification variables that can be added as
     * possible proposals
     * @param expressionIdentifiers Sometimes the expression may have more than one possible identifier,
     * such as <b>ALL</b>, <b>ANY</b> and <b>SOME</b> are a possible JPQL identifier for a single
     * expression ({@link AllOrAnyExpression}
     */
    protected void visitSingleEncapsulatedExpression(AbstractSingleEncapsulatedExpression expression,
                                                     IdentificationVariableType identificationVariableType,
                                                     String... expressionIdentifiers) {

        if (isFollowingInvalidExpression(expression)) {
            return;
        }

        int position = queryPosition.getPosition(expression) - corrections.peek();
        String actualIdentifier = expression.getIdentifier();
        boolean added = false;

        for (String identifier : expressionIdentifiers) {

            // Within the identifier
            if (isPositionWithin(position, actualIdentifier)) {

                addFunctionIdentifiers(expression);

                // If the expression is marked as bad, then the identifiers
                // for the encapsulated expression are no added
                if (!isWithinInvalidExpression(expression)) {
                    for (String jpqlIdentifier : expressionIdentifiers) {
                        proposals.addIdentifier(identifier);
                    }
                }
                // Remove any identifier that got added by addAdditionalFunctions()
                else {
                    for (String jpqlIdentifier : expressionIdentifiers) {
                        proposals.removeIdentifier(identifier);
                    }
                }
            }
            // Right after "<identifier>("
            else if (expression.hasLeftParenthesis()) {
                int length = identifier.length() + 1 /* '(' */;

                if (!added && (position == length)) {
                    added = true;

                    addIdentificationVariables(expression, identificationVariableType);

                    String queryBNF = expression.getEncapsulatedExpressionQueryBNFId();
                    addFunctionIdentifiers(queryBNF);
                    addClauseIdentifiers(queryBNF);
                }
            }
        }
    }

    /**
     * Visits the given {@link AbstractSelectStatement} and checks to see if the identifiers of the
     * following clauses can be added a valid proposals.
     *
     * @param expression
     * @param helper This helper handles one clause from the given <code><b>SELECT</b></code> statement
     */
    @SuppressWarnings("unchecked")
    protected <T extends Expression> void visitStatement(T expression, StatementHelper<T> helper) {

        lockedExpressions.add(expression);

        try {
            int position = queryPosition.getPosition(expression);
            int length = 0;

            while (helper != null) {

                // Add the length of the clause to the current length
                Expression clause = helper.getClause(expression);
                length += clause.getLength();

                // Within the clause, not handled here
                if (position < length) {
                    break;
                }

                // Now check if the clause is complete
                boolean complete = false;

                // At the end of the clause
                if (position == length) {
                    // Check to see if the following clause identifiers can be appended
                    // Example: "SELECT e f|"                 <- FROM can be a valid proposal
                    // Example: "SELECT AVG(e.age)|"          <- No clause identifiers can be added
                    // Example: "SELECT e FROM Employee e|"   <- No clause identifiers can be added
                    // Example: "SELECT e FROM Employee e H|" <- HAVING can be a valid proposal
                    complete = isClauseAppendable(clause);
                }
                // Check whether a whitespace is after the clause (owned by the select statement)
                else if (helper.hasSpaceAfterClause(expression)) {
                    length++;

                    if (position == length) {

                        // Ask the helper to visit the clause's expression
                        // Example: "SELECT e FROM Employee e WHERE e.name = 'JPQL' |"
                        //           AND|OR can be added as valid proposals
                        visitEndingExpression(clause);

                        // Check to see if the following clause identifiers can be appended
                        // Example: "SELECT e |"                  <- FROM can be a valid proposal
                        // Example: "SELECT AVG(e.age) |"         <- FROM can be a valid proposal
                        // Example: "SELECT e FROM Employee e |"  <- The following clause identifiers can be valid proposals
                        complete = helper.isClauseComplete(expression);
                    }
                }

                // Continue to with the next helper
                if (!complete) {
                    helper = (StatementHelper<T>) helper.getNextHelper();
                }
                // Add the following clause identifiers until one is defined
                else {

                    // Append any internal clause identifiers
                    helper.addInternalClauseProposals(expression);

                    // Iterate through the helpers for the following clauses
                    do {
                        helper = (StatementHelper<T>) helper.getNextHelper();

                        if (helper != null) {

                            // Add the clause identifiers
                            helper.addClauseProposals();

                            // The following clauses cannot be added because either
                            // the clause is required or defined
                            if (helper.isRequired() || helper.hasClause(expression)) {
                                helper = null;
                            }
                        }

                    }
                    while (helper != null);
                }
            }
        }
        finally {
            lockedExpressions.pop();
        }
    }

    /**
     * Visits the given {@link AbstractPathExpression} and attempts to find valid proposals that is
     * not provided by the default implementation. Subclasses can add additional proposals that is
     * outside of the scope of generic JPA metadata.
     *
     * @param expression The {@link AbstractPathExpression} to inspect
     * @param variableName The beginning of the path expression
     */
    protected void visitThirdPartyPathExpression(AbstractPathExpression expression,
                                                 String variableName) {
    }

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

        /**
         * Flag used to determine if JPQL identifiers can be appended to the expression.
         */
        protected boolean appendable;

        /**
         * Disposes of the internal data.
         */
        public void dispose() {
            appendable = false;
        }

        /**
         * Determines whether JPQL identifiers can be appended to the expression.
         *
         * @return <code>true</code>
         */
        public boolean isAppendable() {
            return appendable;
        }
    }

    // Made static for performance reasons.
    /**
     * Common helper with visitor reference.
     */
    private static abstract class AbstractVisitorHelper {

        /**
         * Enclosing visitor instance.
         */
        protected final AbstractContentAssistVisitor visitor;

        AbstractVisitorHelper(AbstractContentAssistVisitor visitor) {
            this.visitor = visitor;
        }

    }

    // Made static for performance reasons.
    /**
     * This helper handles adding proposals within a conditional expression that might be parsed as
     * a single expression or has a collection of expression, which means the fragment is either
     * incomplete or invalid.
     */
    protected static abstract class AbstractConditionalClauseCollectionHelper<T extends Expression>
            extends AbstractVisitorHelper implements CollectionExpressionHelper<T> {

        protected AbstractConditionalClauseCollectionHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public void addAtTheEndOfChild(Expression expression,
                                       CollectionExpression collectionExpression,
                                       int index,
                                       boolean hasComma,
                                       boolean virtualSpace) {

            // Coming from addTheBeginningOfChild(), require to bypass the above check
            if (index < 0) {
                index = (-index / 10) - 1;
            }

            // The only thing that is appendable is an arithmetic operator
            // Example: "SELECT e FROM Employee e WHERE e.name|"
            // Example: "SELECT e FROM Employee e WHERE I|"
            if ((index == 0) && !virtualSpace) {

                Expression child = collectionExpression.getChild(0);

                if (visitor.areArithmeticSymbolsAppendable(child)) {
                    visitor.addArithmeticIdentifiers();
                }
            }
            else {

                Object[] result = findChild(collectionExpression, index);

                if (result == null) {
                    return;
                }

                Expression child = (Expression) result[0];
                boolean hasIs  = (Boolean) result[1];
                boolean hasNot = (Boolean) result[2];

                // If 'IS' or 'IS NOT' is present, then none of the following are valid proposals
                if (!hasIs && !hasNot) {

                    if (visitor.areLogicalSymbolsAppendable(child)) {
                        visitor.addLogicalIdentifiers();
                    }

                    if (visitor.areArithmeticSymbolsAppendable(child)) {
                        visitor.addArithmeticIdentifiers();
                    }

                    if (visitor.areComparisonSymbolsAppendable(child)) {
                        visitor.addComparisonIdentifiers(child);
                    }
                }

                if (visitor.isCompoundable(child)) {
                    visitor.addCompoundIdentifiers(ConditionalExpressionBNF.ID, child, hasIs, hasNot);
                }
            }
        }

        @Override
        public void addIdentifier(Expression expression, String identifier) {
            visitor.proposals.addIdentifier(identifier);
        }

        @Override
        public void addTheBeginningOfChild(Expression expression,
                                           CollectionExpression collectionExpression,
                                           int index,
                                           boolean hasComma) {

            if (index == 0) {

                visitor.addIdentificationVariables();
                visitor.addFunctionIdentifiers(ConditionalExpressionBNF.ID);

                if ((collectionExpression != null) &&
                        visitor.isSubqueryAppendable(collectionExpression.getChild(index))) {

                    visitor.addIdentifier(SELECT);
                }
            }
            else {
                addAtTheEndOfChild(expression, collectionExpression, index * -10, hasComma, true);
            }
        }

        @Override
        public boolean canContinue(Expression expression,
                                   CollectionExpression collectionExpression,
                                   int index) {

            Expression child = collectionExpression.getChild(index);

            if (visitor.isNotExpression(child)) {
                return true;
            }

            String text = child.toParsedText();

            return text.equalsIgnoreCase(IS)  ||
                   text.equalsIgnoreCase(NOT) ||
                   text.equalsIgnoreCase("IS NOT");
        }

        /**
         * Handles a special case for a compound identifier like 'IS EMPTY' or 'IS NOT EMPTY'.
         *
         * @param collectionExpression The {@link CollectionExpression} is used to find the {@link
         * Expression} to use when filtering out compound identifier
         * @param index The position to start the search, which goes from that index to the beginning
         * @return An array of three elements. The first one is the child {@link Expression} that can
         * be used when filtering out compound identifier. The second boolean element indicates if
         * <code><b>IS</b></code> was detected after the child. The third boolean element indicates if
         * <code><b>NOT</b></code> was detected after the child, which would also be after <code><b>IS</b></code>
         * if it was detected. <code>null</code> is returned if nothing could be found
         */
        protected Object[] findChild(CollectionExpression collectionExpression, int index) {

            boolean notFound = false;
            boolean isFound = false;
            boolean scanPrevious = false;

            for (; index > -1; index--) {

                Expression child = collectionExpression.getChild(index);
                String text = child.toParsedText();

                // Handle 'NOT'
                if (text.equalsIgnoreCase(NOT) || visitor.isNotExpression(child)) {

                    // Two consecutive 'NOT' or 'IS' is invalid or 'NOT IS' is not valid
                    if (isFound || notFound) {
                        break;
                    }

                    notFound = true;
                }
                // Handle 'IS'
                else if (text.equalsIgnoreCase(IS)) {

                    // Two consecutive 'IS' is invalid
                    if (isFound) {
                        break;
                    }

                    isFound = true;
                }
                else if ("IS NOT".equalsIgnoreCase(text)) {

                    // Two consecutive 'NOT' or 'IS' is invalid or 'NOT IS' is not valid
                    if (isFound || notFound) {
                        break;
                    }

                    isFound  = true;
                    notFound = true;
                }
                // Anything else
                else {

                    // Make sure the previous item is not 'IS', this can happen
                    // when the correction value is changed (happens with IdentificationVariable)
                    if (index > 0) {
                        Object[] result = findChild(collectionExpression, index - 1);
                        isFound  |= (Boolean) result[1];
                        notFound |= (Boolean) result[2];
                    }

                    return new Object[] { child, isFound, notFound };
                }
            }

            return null;
        }

        @Override
        public int maxCollectionSize(Expression expression) {
            // The actual number is 0 but an incomplete fragment like "WHERE e.phoneNumbers IS N"
            // is a collection of 3 expressions
            return Integer.MAX_VALUE;
        }

        @Override
        public int preExpressionLength(Expression expression) {
            return 0;
        }

        @Override
        public JPQLQueryBNF queryBNF(Expression expression, int index) {
            return visitor.getQueryBNF(ConditionalExpressionBNF.ID);
        }
    }

    // Made static for performance reasons.
    protected static abstract class AbstractFromClauseStatementHelper<T extends AbstractSelectStatement>
            extends AbstractVisitorHelper implements StatementHelper<T> {

        protected AbstractFromClauseStatementHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public void addClauseProposals() {
            visitor.addIdentifier(FROM);
        }

        @Override
        public void addInternalClauseProposals(T expression) {
            // Does not have internal clauses
        }

        @Override
        public Expression getClause(T expression) {
            return expression.getFromClause();
        }

        @Override
        public boolean hasClause(T expression) {
            return expression.hasFromClause();
        }

        @Override
        public boolean hasSpaceAfterClause(T expression) {
            return expression.hasSpaceAfterFrom();
        }

        @Override
        public boolean isClauseComplete(T expression) {
            return visitor.isComplete(expression.getFromClause());
        }

        @Override
        public boolean isRequired() {
            return true;
        }
    }

    // Made static for performance reasons.
    protected static abstract class AbstractGroupByClauseStatementHelper<T extends AbstractSelectStatement>
            extends AbstractVisitorHelper implements StatementHelper<T> {

        protected AbstractGroupByClauseStatementHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public void addClauseProposals() {
            visitor.addCompositeIdentifier(GROUP_BY, -1);
        }

        @Override
        public void addInternalClauseProposals(T expression) {
            // Does not have internal clauses
        }

        @Override
        public Expression getClause(T expression) {
            return expression.getGroupByClause();
        }

        @Override
        public boolean hasClause(T expression) {
            return expression.hasGroupByClause();
        }

        @Override
        public boolean hasSpaceAfterClause(T expression) {
            return expression.hasSpaceAfterGroupBy();
        }

        @Override
        public boolean isClauseComplete(T expression) {
            return visitor.isComplete(expression.getGroupByClause());
        }

        @Override
        public boolean isRequired() {
            return false;
        }
    }

    // Made static for performance reasons.
    protected static abstract class AbstractHavingClauseStatementHelper<T extends AbstractSelectStatement>
            extends AbstractVisitorHelper implements StatementHelper<T> {

        protected AbstractHavingClauseStatementHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public void addClauseProposals() {
            visitor.addIdentifier(HAVING);
        }

        @Override
        public void addInternalClauseProposals(T expression) {
            // Does not have internal clauses
        }

        @Override
        public Expression getClause(T expression) {
            return expression.getHavingClause();
        }

        @Override
        public boolean hasClause(T expression) {
            return expression.hasHavingClause();
        }

        @Override
        public boolean isClauseComplete(T expression) {
            return  visitor.isComplete(expression.getHavingClause());
        }

        @Override
        public boolean isRequired() {
            return false;
        }
    }

    // Made static for performance reasons.
    protected static abstract class AbstractSelectClauseCollectionHelper<T extends AbstractSelectClause>
            extends AbstractVisitorHelper implements CollectionExpressionHelper<T> {

        protected AbstractSelectClauseCollectionHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public void addAtTheEndOfChild(T expression,
                                       CollectionExpression collectionExpression,
                                       int index,
                                       boolean hasComma,
                                       boolean virtualSpace) {

            // The only thing that is appendable is an arithmetic operator
            // Example: "SELECT e.name|"
            // Example: "SELECT e|"
            if (queryBNF(expression, index).handleAggregate()) {

                Expression child = collectionExpression.getChild(index);

                if (visitor.areArithmeticSymbolsAppendable(child)) {
                    visitor.addArithmeticIdentifiers();
                }
            }
        }

        @Override
        public void addIdentifier(T expression, String identifier) {
            visitor.proposals.addIdentifier(identifier);
        }

        @Override
        public void addTheBeginningOfChild(T expression,
                                           CollectionExpression collectionExpression,
                                           int index,
                                           boolean hasComma) {

            if ((index == 0) || hasComma) {
                visitor.addIdentificationVariables();
                visitor.addFunctionIdentifiers(expression.getSelectItemQueryBNFId());
            }
        }

        @Override
        public CollectionExpression buildCollectionExpression(T expression) {
            CollectionExpression collectionExpression = visitor.getCollectionExpression(expression.getSelectExpression());
            if (collectionExpression == null) {
                collectionExpression = expression.buildCollectionExpression();
            }
            return collectionExpression;
        }

        @Override
        public boolean canContinue(T expression, CollectionExpression collectionExpression, int index) {
            return false;
        }

        @Override
        public boolean hasDelimiterAfterIdentifier(T expression) {
            return expression.hasSpaceAfterSelect();
        }

        @Override
        public int maxCollectionSize(T expression) {
            return Integer.MAX_VALUE;
        }

        @Override
        public int preExpressionLength(T expression) {
            return 0;
        }

        @Override
        public JPQLQueryBNF queryBNF(T expression, int index) {
            return visitor.getQueryBNF(expression.getSelectItemQueryBNFId());
        }
    }

    // Made static for performance reasons.
    protected static abstract class AbstractSelectClauseStatementHelper
            extends AbstractVisitorHelper implements StatementHelper<AbstractSelectStatement> {

        protected AbstractSelectClauseStatementHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public void addClauseProposals() {
            visitor.addIdentifier(SELECT);
        }

        @Override
        public void addInternalClauseProposals(AbstractSelectStatement expression) {
            // Does not have internal clauses
        }

        @Override
        public Expression getClause(AbstractSelectStatement expression) {
            return expression.getSelectClause();
        }

        @Override
        public boolean hasClause(AbstractSelectStatement expression) {
            return expression.hasSelectClause();
        }

        @Override
        public boolean hasSpaceAfterClause(AbstractSelectStatement expression) {
            return expression.hasSpaceAfterSelect();
        }

        @Override
        public boolean isClauseComplete(AbstractSelectStatement expression) {
            return visitor.isComplete(expression.getSelectClause());
        }

        @Override
        public boolean isRequired() {
            return true;
        }

    }

    // Made static for performance reasons.
    protected static abstract class AbstractWhereClauseSelectStatementHelper<T extends AbstractSelectStatement>
            extends AbstractVisitorHelper implements StatementHelper<T> {

        protected AbstractWhereClauseSelectStatementHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public void addClauseProposals() {
            visitor.addIdentifier(WHERE);
        }

        @Override
        public void addInternalClauseProposals(T expression) {
            // Does not have internal clauses
        }

        @Override
        public Expression getClause(T expression) {
            return expression.getWhereClause();
        }

        @Override
        public boolean hasClause(T expression) {
            return expression.hasWhereClause();
        }

        @Override
        public boolean hasSpaceAfterClause(T expression) {
            return expression.hasSpaceAfterWhere();
        }

        @Override
        public boolean isClauseComplete(T expression) {
            return visitor.isComplete(expression.getWhereClause());
        }

        @Override
        public boolean isRequired() {
            return false;
        }
    }

    // Made static for performance reasons.
    /**
     * This visitor retrieves the permitted type from the path expression's parent. For instance,
     * <b>SUM</b> or <b>AVG</b> only accepts state fields that have a numeric type.
     */
    protected static abstract class AcceptableTypeVisitor extends AbstractExpressionVisitor {

        /**
         * The type that is retrieved based on the expression, it determines what is acceptable.
         */
        protected IType type;

        /**
         * Disposes of the internal data.
         */
        public void dispose() {
            type = null;
        }

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

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

    // Made static for performance reasons.
    /**
     * This visitor scans the visited {@link Expression} and determines if a JPQL identifier can be
     * added ("appended") when the position of the cursor is at the end of the expression.
     * <p>
     * For instance:
     * <ul>
     * <li>In "<code>SELECT e, AVG(e.age) F|</code>", F is parsed as a result variable but
     * can also be seen as the first letter for <b>FROM</b>;</li>
     * <li>In "<code>SELECT e FROM Employee e WHERE e.name |</code>", the compound identifiers can be
     * added, eg: 'IS NOT NULL', or '=', etc</li>
     * <li>In "<code>SELECT e FROM Employee e WHERE e.name NOT B|</code>", only the composite
     * identifier "BETWEEN" and "NOT BETWEEN" can be added because the <code>NOT</code> expression
     * does not have a valid expression: "B" is not a valid expression.</li>
     * <li>In "<code>SELECT e FROM Employee e FROM e.age|</code>", the arithmetic and comparison
     * identifiers are allowed, but the logical and compound identifiers.</li>
     * </ul>
     */
    protected static class AppendableExpressionVisitor extends AbstractAppendableExpressionVisitor {

        /**
         * Enclosing visitor instance.
         */
        protected final AbstractContentAssistVisitor visitor;

        /**
         * The type of the JPQL identifiers can can be possible proposals.
         */
        protected AppendableType appendableType;

        /**
         * Internal flag indicating if a clause is being visited which can have a collection of children.
         */
        protected boolean clauseOfItems;

        /**
         * Caches the visited {@link CollectionExpression} so a child could use it.
         */
        protected CollectionExpression collectionExpression;

        /**
         * Internal flag indicating the {@link Expression} being visited is a conditional expression.
         */
        protected boolean conditionalExpression;

        /**
         * When visiting a {@link CollectionExpression}, this indicates if there is a comma before the
         * child being visited.
         */
        protected boolean hasComma;

        /**
         * When visiting a {@link CollectionExpression}, this indicates the position within that
         * collection of the child being visited.
         */
        protected int positionInCollection;

        /**
         * Internal flag indicating the {@link Expression} being visited is encapsulated by parenthesis.
         */
        protected boolean subExpression;

        /**
         * Creates a new <code>AppendableExpressionVisitor</code>.
         */
        AppendableExpressionVisitor(AbstractContentAssistVisitor visitor) {
            super();
            this.visitor = visitor;
            this.positionInCollection = -1;
        }

        @Override
        public void visit(AbsExpression expression) {
            appendable = !conditionalExpression &&
                         expression.hasRightParenthesis();
        }

        @Override
        public void visit(AbstractSchemaName expression) {
            appendable = !conditionalExpression;
        }

        @Override
        public void visit(AdditionExpression expression) {
            if (expression.hasRightExpression()) {
                expression.getRightExpression().accept(this);
            }
        }

        @Override
        public void visit(AllOrAnyExpression expression) {
            appendable = !conditionalExpression &&
                      expression.hasRightParenthesis();
        }

        @Override
        public void visit(AndExpression expression) {
            if (expression.hasRightExpression()) {
                expression.getRightExpression().accept(this);
            }
        }

        @Override
        public void visit(ArithmeticFactor expression) {
            if (expression.hasExpression()) {
                expression.getExpression().accept(this);
            }
        }

        @Override
        public void visit(AvgFunction expression) {
            appendable = !conditionalExpression &&
                      expression.hasRightParenthesis();
        }

        @Override
        public void visit(BadExpression expression) {
            appendable = true;
        }

        @Override
        public void visit(BetweenExpression expression) {

            // Example 2: "x BETWEEN y A" is not complete
            // Example 1: "x between y SQRT(e.age)" is seen as complete
            if (!expression.hasAnd()) {

                String variable = visitor.queryContext.literal(
                    expression.getUpperBoundExpression(),
                    LiteralType.IDENTIFICATION_VARIABLE
                );

                if (variable != ExpressionTools.EMPTY_STRING) {
                    appendable = false;
                }
                else {
                    expression.getUpperBoundExpression().accept(this);
                }
            }
            else {
                boolean oldConditionalExpression = conditionalExpression;
                conditionalExpression = false;
                expression.getUpperBoundExpression().accept(this);
                conditionalExpression = oldConditionalExpression;
            }
        }

        @Override
        public void visit(CaseExpression expression) {
            appendable = !conditionalExpression &&
                         expression.hasEnd();
        }

        @Override
        public void visit(CoalesceExpression expression) {
            appendable = !conditionalExpression &&
                      expression.hasRightParenthesis();
        }

        @Override
        public void visit(CollectionExpression expression) {

            collectionExpression = expression;
            positionInCollection = expression.childrenSize() - 1;
            hasComma = expression.hasComma(positionInCollection - 1);

            if ((appendableType == AppendableType.CLAUSE) &&
                (positionInCollection + 1 < collectionExpression.childrenSize())) {

                appendable = false;
            }
            else {
                expression.accept(positionInCollection, this);
            }

            hasComma = false;
            positionInCollection = -1;
            collectionExpression = null;
        }

        @Override
        public void visit(CollectionMemberDeclaration expression) {

            if (appendableType == AppendableType.COMPLETE) {
                if (expression.hasIdentificationVariable()) {
                    expression.getIdentificationVariable().accept(this);
                }
            }
            else {
                // Only the identifier is parsed
                appendable = !expression.hasAs()                         &&
                             !expression.hasSpaceAfterIn()               &&
                             !expression.hasLeftParenthesis()            &&
                             !expression.hasRightParenthesis()           &&
                             !expression.hasIdentificationVariable()     &&
                             !expression.hasSpaceAfterRightParenthesis() &&
                             !expression.hasCollectionValuedPathExpression();
            }
        }

        @Override
        public void visit(CollectionMemberExpression expression) {

            // Only AND, OR, NOT or clause identifiers can be followed this expression
            appendable = (appendableType == AppendableType.LOGICAL   ||
                          appendableType == AppendableType.COMPLETE) &&
                          expression.hasCollectionValuedPathExpression();

            if (appendable) {
                boolean oldConditionalExpression = conditionalExpression;
                conditionalExpression = false;
                expression.getCollectionValuedPathExpression().accept(this);
                conditionalExpression = oldConditionalExpression;
            }
        }

        @Override
        public void visit(CollectionValuedPathExpression expression) {
            appendable = !conditionalExpression &&
                      !expression.endsWithDot();
        }

        @Override
        public void visit(ComparisonExpression expression) {

            if (appendableType == AppendableType.ARITHMETIC ||
                appendableType == AppendableType.COMPARISON ||
                appendableType == AppendableType.COMPOUNDABLE) {

                appendable = false;
            }
            // "x = y |" <- AND and OR are valid proposals
            // "(x = y) |" <- AND and OR are valid proposals
            else if (appendableType == AppendableType.LOGICAL) {
                AppendableType oldAppendableType = appendableType;
                appendableType = AppendableType.COMPLETE;
                expression.getRightExpression().accept(this);
                appendableType = oldAppendableType;
            }
            else if (expression.hasRightExpression()) {
                boolean oldConditionalExpression = conditionalExpression;
                conditionalExpression = false;
                expression.getRightExpression().accept(this);
                conditionalExpression = oldConditionalExpression;
            }
        }

        @Override
        public void visit(ConcatExpression expression) {
            appendable = !conditionalExpression &&
                      expression.hasRightParenthesis();
        }

        @Override
        public void visit(ConstructorExpression expression) {
            appendable = !conditionalExpression &&
                      expression.hasRightParenthesis();
        }

        @Override
        public void visit(CountFunction expression) {
            appendable = !conditionalExpression &&
                      expression.hasRightParenthesis();
        }

        @Override
        public void visit(DateTime expression) {

            if (conditionalExpression && (appendableType == AppendableType.COMPLETE)) {
                appendable = false;
            }
            else {
                appendable = // Valid ending
                             (!expression.isJDBCDate()                    ||
                              expression.toActualText().endsWith("}"))    &&
                             // Valid AppendableType
                             (appendableType == AppendableType.ARITHMETIC ||
                              appendableType == AppendableType.COMPARISON ||
                              appendableType == AppendableType.COMPLETE   ||
                              appendableType == AppendableType.COMPOUNDABLE);
            }
        }

        @Override
        public void visit(DeleteClause expression) {
            if (expression.hasRangeVariableDeclaration()) {
                expression.getRangeVariableDeclaration().accept(this);
            }
        }

        @Override
        public void visit(DeleteStatement expression) {

            if (expression.hasWhereClause()) {
                expression.getWhereClause().accept(this);
            }
            else {
                expression.getDeleteClause().accept(this);
            }
        }

        @Override
        public void visit(DivisionExpression expression) {
            if (expression.hasRightExpression()) {
                expression.getRightExpression().accept(this);
            }
        }

        @Override
        public void visit(EmptyCollectionComparisonExpression expression) {

            // Only AND, OR, NOT or clause identifiers can follow this expression
            // when the type is LOGICAL or CLAUSE
            appendable = appendableType == AppendableType.COMPLETE ||
                         appendableType == AppendableType.LOGICAL;
        }

        @Override
        public void visit(EntityTypeLiteral expression) {
            appendable = !conditionalExpression;
        }

        @Override
        public void visit(EntryExpression expression) {
            appendable = !conditionalExpression &&
                      expression.hasRightParenthesis();
        }

        @Override
        public void visit(ExistsExpression expression) {

            // Only AND, OR, NOT or clause identifiers can follow this expression
            // when the type is LOGICAL or CLAUSE
            appendable = (appendableType == AppendableType.COMPLETE ||
                          appendableType == AppendableType.LOGICAL) &&
                          expression.hasRightParenthesis();
        }

        @Override
        protected void visit(Expression expression) {

            // Anything other than what's a valid conditional expression is not valid
            // "... WHERE AVG(a.ge) " <- Invalid and the following clauses cannot be appended
            appendable = false;
        }

        @Override
        public void visit(FromClause expression) {

            if (expression.hasAsOfClause()) {
                expression.getAsOfClause().accept(this);
            }
            else if (expression.hasHierarchicalQueryClause()) {
                expression.getHierarchicalQueryClause().accept(this);
            }
            else if (expression.hasDeclaration()) {
                clauseOfItems = true;
                expression.getDeclaration().accept(this);
                clauseOfItems = false;
            }
        }

        @Override
        public void visit(FunctionExpression expression) {
            appendable = !conditionalExpression &&
                      expression.hasRightParenthesis();
        }

        @Override
        public void visit(GroupByClause expression) {

            if (expression.hasGroupByItems()) {
                clauseOfItems = true;
                expression.getGroupByItems().accept(this);
                clauseOfItems = false;
            }
        }

        @Override
        public void visit(HavingClause expression) {
            if (expression.hasConditionalExpression()) {
                conditionalExpression = true;
                expression.getConditionalExpression().accept(this);
                conditionalExpression = false;
            }
        }

        @Override
        public void visit(IdentificationVariable expression) {

            if (appendableType == AppendableType.COMPLETE) {
                appendable = true;
            }
            // The WHERE/HAVING clauses do not have a collection of expressions but has an
            // aggregation of expressions. If the appendable type is CLASUE, then the only
            // possible way for this to be valid is to have a collection of expressions where
            // the first child is the conditional expression and the second child is the
            // beginning of the following clause.
            // Example: "SELECT e FROM Employee e G|" <- appendable
            // Example: "SELECT e FROM Employee e WHERE e.phoneNumbers IS NOT E|" <- Not appendable
            else if (clauseOfItems || (!clauseOfItems && (appendableType == AppendableType.CLAUSE))) {
                appendable = !hasComma                   &&
                             (positionInCollection > -1) &&
                             !visitor.isFollowingInvalidExpression(expression);
            }
            else {

                // Special case if what's before is 'IS' or 'IS NOT', then it's not appendable
                if (positionInCollection > 1) {
                    Expression child = collectionExpression.getChild(positionInCollection - 1);
                    String text = child.toActualText();
                    appendable = !text.equals(IS) && !text.equals("IS NOT");
                }
                else {
                    switch (appendableType) {
                        case ARITHMETIC: {
                            appendable = false;
                            break;
                        }
                        case SUBQUERY:
                        case LOGICAL:
                        case COMPOUNDABLE: {
                            appendable = true;
//                            appendable = (positionInCollection > -1) || subExpression;
                            break;
                        }
                        case CLAUSE: {
                            appendable = false;
                            break;
                        }
                        case COMPARISON:
                        case COMPLETE: {
                            appendable = true;
                            break;
                        }
                    }
                }
            }
        }

        @Override
        public void visit(IdentificationVariableDeclaration expression) {

            // 1) The FROM clause needs to have more than one identification variable declaration
            //    before the next clauses identifiers can be added. Example: "SELECT e FROM E" where
            //    'E' cannot be the beginning of a clause identifier
            // 2) The next clause identifiers cannot be added if there is a comma before the last
            //    item. Example: "SELECT e FROM Employee e, I" where 'I' cannot be the beginning of
            //    a clause identifier
            if ((appendableType != AppendableType.COMPLETE) && ((positionInCollection == -1) || hasComma)) {
                appendable = false;
            }
            else if (expression.hasJoins()) {
                expression.getJoins().accept(this);
            }
            else {
                expression.getRangeVariableDeclaration().accept(this);
            }
        }

        @Override
        public void visit(IndexExpression expression) {
            appendable = !conditionalExpression &&
                      expression.hasRightParenthesis();
        }

        @Override
        public void visit(InExpression expression) {

            // Only AND, OR, NOT or clause identifiers can follow this expression
            // when the type is LOGICAL or CLAUSE
            appendable = (appendableType == AppendableType.COMPLETE ||
                          appendableType == AppendableType.LOGICAL) &&
                          expression.hasRightParenthesis();
        }

        @Override
        public void visit(InputParameter expression) {
            appendable = !conditionalExpression;
        }

        @Override
        public void visit(Join expression) {

            if (expression.hasOnClause()) {
                expression.getOnClause().accept(this);
            }
            else if (expression.hasFetch()) {
                if (expression.hasAs()) {
                    appendable = expression.hasIdentificationVariable();
                }
                else {
                    appendable = expression.hasJoinAssociationPath();
                }
            }
            else {
                appendable = expression.hasIdentificationVariable();
            }
        }

        @Override
        public void visit(KeyExpression expression) {
            appendable = !conditionalExpression &&
                      expression.hasRightParenthesis();
        }

        @Override
        public void visit(KeywordExpression expression) {
            // Nothing can be added right after NULL, TRUE, FALSE
            appendable = !conditionalExpression &&
                      (appendableType == AppendableType.LOGICAL ||
                       appendableType == AppendableType.COMPLETE);
        }

        @Override
        public void visit(LengthExpression expression) {
            appendable = !conditionalExpression &&
                      expression.hasRightParenthesis();
        }

        @Override
        public void visit(LikeExpression expression) {

            // Only AND, OR, NOT or clause identifiers can follow this expression
            // when the type is LOGICAL or CLAUSE
            appendable = appendableType == AppendableType.COMPLETE ||
                         appendableType == AppendableType.LOGICAL;

            if (appendable) {

                boolean oldConditionalExpression = conditionalExpression;
                conditionalExpression = false;

                if (expression.hasEscape()) {
                    expression.getEscapeCharacter().accept(this);
                }
                else {
                    expression.getPatternValue().accept(this);
                }

                conditionalExpression = oldConditionalExpression;
            }
        }

        @Override
        public void visit(LocateExpression expression) {
            appendable = !conditionalExpression &&
                      expression.hasRightParenthesis();
        }

        @Override
        public void visit(LowerExpression expression) {
            appendable = !conditionalExpression &&
                      expression.hasRightParenthesis();
        }

        @Override
        public void visit(MaxFunction expression) {
            appendable = !conditionalExpression &&
                      expression.hasRightParenthesis();
        }

        @Override
        public void visit(MinFunction expression) {
            appendable = !conditionalExpression &&
                      expression.hasRightParenthesis();
        }

        @Override
        public void visit(ModExpression expression) {
            appendable = !conditionalExpression &&
                      expression.hasRightParenthesis();
        }

        @Override
        public void visit(MultiplicationExpression expression) {
            if (expression.hasRightExpression()) {
                expression.getRightExpression().accept(this);
            }
        }

        @Override
        public void visit(NotExpression expression) {

            // Example: "NOT B" can only have compound identifiers like 'NOT BETWEEN'
            if (expression.hasExpression()) {

                String variable = visitor.queryContext.literal(
                    expression.getExpression(),
                    LiteralType.IDENTIFICATION_VARIABLE
                );

                if (variable != ExpressionTools.EMPTY_STRING) {
                    appendable = (appendableType == AppendableType.COMPOUNDABLE);
                }
                else {
                    boolean oldConditionalExpression = conditionalExpression;
                    conditionalExpression = false;
                    expression.getExpression().accept(this);
                    conditionalExpression = oldConditionalExpression;
                }
            }
        }

        @Override
        public void visit(NullComparisonExpression expression) {

            // Only AND, OR, NOT or clause identifiers can follow this expression
            // when the type is LOGICAL or CLAUSE
            appendable = appendableType == AppendableType.COMPLETE ||
                         appendableType == AppendableType.LOGICAL;
        }

        @Override
        public void visit(NullIfExpression expression) {
            appendable = !conditionalExpression &&
                      expression.hasRightParenthesis();
        }

        @Override
        public void visit(NumericLiteral expression) {
            appendable = !conditionalExpression;
        }

        @Override
        public void visit(ObjectExpression expression) {
            appendable = !conditionalExpression &&
                      expression.hasRightParenthesis();
        }

        @Override
        public void visit(OnClause expression) {
            if (expression.hasConditionalExpression()) {
                conditionalExpression = true;
                expression.getConditionalExpression().accept(this);
                conditionalExpression = false;
            }
        }

        @Override
        public void visit(OrderByClause expression) {
            if (expression.hasOrderByItems()) {
                clauseOfItems = true;
                expression.getOrderByItems().accept(this);
                clauseOfItems = false;
            }
        }

        @Override
        public void visit(OrderByItem expression) {
            appendable = expression.hasSpaceAfterExpression() &&
                         expression.isDefault() ||
                         expression.hasSpaceAfterOrdering() &&
                        !expression.isNullsFirst() && !expression.isNullsLast();
        }

        @Override
        public void visit(OrExpression expression) {
            if (expression.hasRightExpression()) {
                expression.getRightExpression().accept(this);
            }
        }

        @Override
        public void visit(RangeVariableDeclaration expression) {

            if (appendableType == AppendableType.COMPLETE) {
                if (expression.hasIdentificationVariable()) {
                    expression.getIdentificationVariable().accept(this);
                }
            }
            else {

                // Only the abstract schema name is parsed
                appendable = !expression.hasSpaceAfterRootObject() &&
                             !expression.hasAs() &&
                             !expression.hasIdentificationVariable();

                if (!appendable &&
                    expression.hasRootObject() &&
                    expression.hasIdentificationVariable()) {

                    expression.getIdentificationVariable().accept(this);
                }
            }
        }

        @Override
        public void visit(ResultVariable expression) {
            // The result variable is parsed without AS
            appendable = !expression.hasAs() &&
                         !expression.hasSpaceAfterAs() &&
                          expression.hasResultVariable();
        }

        @Override
        public void visit(SelectClause expression) {
            if (expression.hasSelectExpression()) {
                clauseOfItems = true;
                expression.getSelectExpression().accept(this);
                clauseOfItems = false;
            }
        }

        @Override
        public void visit(SelectStatement expression) {

            if (expression.hasUnionClauses()) {
                expression.getUnionClauses().accept(this);
            }
            else if (expression.hasOrderByClause()) {
                expression.getOrderByClause().accept(this);
            }
            else if (expression.hasHavingClause()) {
                expression.getHavingClause().accept(this);
            }
            else if (expression.hasGroupByClause()) {
                expression.getGroupByClause().accept(this);
            }
            else if (expression.hasWhereClause()) {
                expression.getWhereClause().accept(this);
            }
            else if (expression.hasFromClause()) {
                expression.getFromClause().accept(this);
            }
            else {
                expression.getSelectClause().accept(this);
            }
        }

        @Override
        public void visit(SimpleFromClause expression) {

            if (expression.hasAsOfClause()) {
                expression.getAsOfClause().accept(this);
            }
            else if (expression.hasHierarchicalQueryClause()) {
                expression.getHierarchicalQueryClause().accept(this);
            }
            else if (expression.hasDeclaration()) {
                clauseOfItems = true;
                expression.getDeclaration().accept(this);
                clauseOfItems = true;
            }
        }

        @Override
        public void visit(SimpleSelectClause expression) {

            if (expression.hasSelectExpression()) {
                clauseOfItems = true;
                expression.getSelectExpression().accept(this);
                clauseOfItems = true;
            }
        }

        @Override
        public void visit(SimpleSelectStatement expression) {

            if (subExpression && (appendableType == AppendableType.ARITHMETIC)) {
                appendable = true;
            }
            else {

                if (expression.hasHavingClause()) {
                    expression.getHavingClause().accept(this);
                }
                else if (expression.hasGroupByClause()) {
                    expression.getGroupByClause().accept(this);
                }
                else if (expression.hasWhereClause()) {
                    expression.getWhereClause().accept(this);
                }
                else if (expression.hasFromClause()) {
                    expression.getFromClause().accept(this);
                }
                else {
                    expression.getSelectClause().accept(this);
                }
            }
        }

        @Override
        public void visit(SizeExpression expression) {
            appendable = !conditionalExpression &&
                      expression.hasRightParenthesis();
        }

        @Override
        public void visit(SqrtExpression expression) {
            appendable = !conditionalExpression &&
                      expression.hasRightParenthesis();
        }

        @Override
        public void visit(StateFieldPathExpression expression) {

            // "e.employee." cannot be appended with something
            if (expression.endsWithDot()) {
                appendable = false;
            }
            // "... WHERE e.age "    <- Invalid to be followed by another clause
            // "... GROUP BY e.age " <- Valid to be followed by another clause
            else if (appendableType == AppendableType.CLAUSE ||
                     appendableType == AppendableType.COMPLETE) {

                appendable = !conditionalExpression;
            }
            else {

                // Resolve the mapping so we can determine what is valid based on its type
                IMapping mapping = visitor.queryContext.getMapping(expression);

                if (mapping == null) {
                    appendable = false;
                }
                else {
                    IType type = mapping.getType();

                    switch (appendableType) {
                        case ARITHMETIC: {
                            // e.name (String) cannot be followed by +,-,/,*
                            // e.age (int) can be followed by an arithmetic operator
                            appendable = visitor.queryContext.getTypeHelper().isNumericType(type);
                            break;
                        }
                        case COMPARISON: {
                            TypeHelper typeHelper = visitor.queryContext.getTypeHelper();
                            appendable = !typeHelper.isCollectionType(type) &&
                                         !typeHelper.isMapType(type);
                            break;
                        }
                        case COMPOUNDABLE: {
                            // The type will be calculated later
                            appendable = true;
                            break;
                        }
                        case LOGICAL: {
                            appendable = visitor.queryContext.getTypeHelper().isBooleanType(type);
                            break;
                        }
                    }
                }
            }
        }

        @Override
        public void visit(StringLiteral expression) {
            appendable = !conditionalExpression &&
                      expression.hasCloseQuote();
        }

        @Override
        public void visit(SubExpression expression) {

            if (appendableType == AppendableType.COMPLETE) {
                appendable = expression.hasRightParenthesis();
            }
            else if (expression.hasExpression()) {

                subExpression = true;
                boolean oldConditionalExpression = conditionalExpression;
                conditionalExpression = false;

                expression.getExpression().accept(this);
                appendable &= expression.hasRightParenthesis();

                subExpression = false;
                conditionalExpression = oldConditionalExpression;
            }
            else {
                // Only a subquery could be a valid proposal, everything
                // else cannot start an encapsulated expression
                appendable = (appendableType == AppendableType.SUBQUERY);
            }
        }

        @Override
        public void visit(SubstringExpression expression) {
            appendable = !conditionalExpression &&
                      expression.hasRightParenthesis();
        }

        @Override
        public void visit(SubtractionExpression expression) {
            if (expression.hasRightExpression()) {
                expression.getRightExpression().accept(this);
            }
        }

        @Override
        public void visit(SumFunction expression) {
            appendable = !conditionalExpression &&
                      expression.hasRightParenthesis();
        }

        @Override
        public void visit(TreatExpression expression) {
            appendable = !conditionalExpression &&
                      expression.hasRightParenthesis();
        }

        @Override
        public void visit(TrimExpression expression) {
            appendable = !conditionalExpression &&
                      expression.hasRightParenthesis();
        }

        @Override
        public void visit(TypeExpression expression) {
            appendable = !conditionalExpression &&
                      expression.hasRightParenthesis();
        }

        @Override
        public void visit(UpdateClause expression) {
            if (expression.hasUpdateItems()) {
                expression.getUpdateItems().accept(this);
            }
        }

        @Override
        public void visit(UpdateItem expression) {
            expression.getNewValue().accept(this);
        }

        @Override
        public void visit(UpdateStatement expression) {
            if (expression.hasWhereClause()) {
                expression.getWhereClause().accept(this);
            }
            else {
                expression.getUpdateClause().accept(this);
            }
        }

        @Override
        public void visit(UpperExpression expression) {
            appendable = !conditionalExpression &&
                      expression.hasRightParenthesis();
        }

        @Override
        public void visit(ValueExpression expression) {
            appendable = !conditionalExpression &&
                      expression.hasRightParenthesis();
        }

        @Override
        public void visit(WhenClause expression) {
            if (expression.hasWhenExpression()) {
                conditionalExpression = true;
                expression.getWhenExpression().accept(this);
                conditionalExpression = false;
            }
        }

        @Override
        public void visit(WhereClause expression) {
            if (expression.hasConditionalExpression()) {
                conditionalExpression = true;
                expression.getConditionalExpression().accept(this);
                conditionalExpression = false;
            }
        }
    }

    // Made static for performance reasons.
    /**
     * This is used to determine how {@link AppendableExpressionVisitor} should perform the check.
     */
    protected static enum AppendableType {

        /**
         * Determines whether the arithmetic operators (+, -, *, /) can be appended as valid proposals.
         */
        ARITHMETIC,

        /**
         * Determines whether the JPQL identifiers identifying a clause (eg: <code><b>WHERE</b></code>)
         * can be appended as valid proposals.
         */
        CLAUSE,

        /**
         * Determines whether the comparison operators {@literal (<, <=, <>, >=, =)} can be appended as valid proposals.
         */
        COMPARISON,

        /**
         * Determines whether the visited {@link Expression} is grammatically complete by making sure
         * its ending is valid.
         */
        COMPLETE,

        /**
         * Determines whether the compound identifiers (eg: <code><b>IS NULL</b></code>) can be
         * appended as valid proposals.
         */
        COMPOUNDABLE,

        /**
         * Determines whether the logical identifiers (<code><b>AND</b></code> and <code><b>OR</b></code>)
         * can be appended as valid proposals.
         */
        LOGICAL,

        /**
         * Determines whether the JPQL identifiers identifying a subquery (eg: <code><b>SELECT</b></code>)
         * can be appended as valid proposals.
         */
        SUBQUERY
    }

    // Made static for performance reasons.
    /**
     * This helper is used to determine how to add proposals within a collection of expressions. Each
     * expression is usually separated by either a whitespace or by a comma.
     */
    protected static interface CollectionExpressionHelper<T extends Expression> {

        /**
         * Adds the proposals because the cursor is at the end of the child at the given position.
         *
         * @param expression The {@link Expression} being visited
         * @param collectionExpression The {@link CollectionExpression} is either the child of the
         * given {@link Expression} or a temporary generated one that usually contains a single item
         * @param index The position of that child in the collection of children
         * @param hasComma Indicates whether a comma is present before the child at the given position;
         * if the index is 0, then this is <code>false</code> by default
         * @param virtualSpace Indicates if this method is called because the cursor is at the end of
         * the child at the specified index but by considering there is a virtual space at the end of
         * that child
         */
        void addAtTheEndOfChild(T expression,
                                CollectionExpression collectionExpression,
                                int index,
                                boolean hasComma,
                                boolean virtualSpace);

        /**
         * Adds the given JPQL identifier as a valid proposal.
         *
         * @param expression The {@link Expression} being visited
         * @param identifier The JPQL identifier to add as a valid proposal
         */
        void addIdentifier(T expression, String identifier);

        /**
         * Adds the proposals because the cursor is at the beginning of the child {@link Expression}
         * at the given position.
         *
         * @param expression The {@link Expression} being visited
         * @param collectionExpression The {@link CollectionExpression} is either the child of the
         * given {@link Expression} or a temporary generated one that usually contains a single item.
         * This can be null if the position is at the beginning
         * @param index The position of the child that was scanned
         * @param hasComma Indicates whether a comma is present before the child at the given position;
         * if the index is 0, then this is <code>false</code> by default
         */
        void addTheBeginningOfChild(T expression,
                                    CollectionExpression collectionExpression,
                                    int index,
                                    boolean hasComma);

        /**
         * Either returns the given {@link Expression}'s child, which is already a {@link CollectionExpression}
         * or requests this helper to return a "virtual" {@link CollectionExpression} that is wrapping
         * the single element.
         *
         * @param expression The parent of the children to retrieve
         * @return The given expression's child or a "virtual" one
         */
        CollectionExpression buildCollectionExpression(T expression);

        /**
         * Asks this helper if the search can continue even though two child expressions are not
         * separated by a comma.
         *
         * @param expression The {@link Expression} being visited
         * @param collectionExpression The {@link CollectionExpression}
         * @param index The position of the child being scanned
         * @return <code>true</code> if the check can continue even though the previous child was not
         * separated by a comma; <code>false</code> to stop the check
         */
        boolean canContinue(T expression, CollectionExpression collectionExpression, int index);

        /**
         * Determines whether a delimiter like a whitespace or an open parenthesis was parsed after
         * the identifier.
         *
         * @param expression The {@link Expression} being visited
         * @return <code>true</code> if something is present; <code>false</code> otherwise
         */
        boolean hasDelimiterAfterIdentifier(T expression);

        /**
         * Returns the maximum number of encapsulated {@link Expression expressions} the {@link Expression}
         * allows. Some expression only allow 2, others 3 and others allow an unlimited number.
         *
         * @param expression The {@link Expression} for which its maximum number of children
         * @return The maximum number of children the expression can have
         */
        int maxCollectionSize(T expression);

        /**
         * Returns the length of anything that can be defined before the first child. An example can
         * be "<code>DISTINCT </code>" in "<code>AVG(DISTINCT e.name)</code>".
         *
         * @param expression The {@link Expression} being visited
         * @return The length of anything that was parsed before the first child or 0 if nothing was parsed
         */
        int preExpressionLength(T expression);

        /**
         * Returns the {@link JPQLQueryBNF} that defines the fragment at the given position.
         *
         * @param expression The {@link Expression} being visited
         * @param index The position of the element to retrieve the BNF defined in the JPQL grammar
         * @return The {@link JPQLQueryBNF} that defines the fragment at the given position
         */
        JPQLQueryBNF queryBNF(T expression, int index);
    }

    // Made static final for performance reasons.
    /**
     * This visitor retrieves the {@link CollectionExpression} if it is visited.
     */
    protected static final class CollectionExpressionVisitor extends AbstractExpressionVisitor {

        /**
         * The {@link CollectionExpression} if it is the {@link Expression} that was visited.
         */
        protected CollectionExpression expression;

        /**
         * Disposes of the internal data.
         */
        public void dispose() {
            expression = null;
        }

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

    // Made static final for performance reasons.
    protected static final class CollectionMappingFilter implements Filter<IMapping> {

        @Override
        public boolean accept(IMapping value) {
            // Both association and collection field are accepted
            // Example: e.address is incomplete but it is not the entire path
            // Example: e.projects is the complete path
            return value.isRelationship();
        }
    }

    // Made static final for performance reasons.
    protected static final class ConcatExpressionCollectionHelper
            extends AbstractVisitorHelper implements CollectionExpressionHelper<ConcatExpression> {

        protected ConcatExpressionCollectionHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public void addAtTheEndOfChild(ConcatExpression expression,
                                       CollectionExpression collectionExpression,
                                       int index,
                                       boolean hasComma,
                                       boolean virtualSpace) {

            // The only thing that is appendable is an arithmetic operator
            // Example: "SELECT e.name|"
            // Example: "SELECT e|"
            if (queryBNF(expression, index).handleAggregate()) {

                Expression child = collectionExpression.getChild(index);

                if ((index == 0) && !virtualSpace) {

                    if (visitor.areArithmeticSymbolsAppendable(child)) {
                        visitor.addArithmeticIdentifiers();
                    }
                }
                else {

                    if (visitor.areArithmeticSymbolsAppendable(child)) {
                        visitor.addArithmeticIdentifiers();
                    }

                    if (visitor.areComparisonSymbolsAppendable(child)) {
                        visitor.addComparisonIdentifiers(child);
                    }
                }
            }
        }

        @Override
        public void addIdentifier(ConcatExpression expression, String identifier) {
            visitor.proposals.addIdentifier(identifier);
            visitor.addIdentificationVariables();
            visitor.addFunctionIdentifiers(expression.getParent().findQueryBNF(expression));
        }

        @Override
        public void addTheBeginningOfChild(ConcatExpression expression,
                                           CollectionExpression collectionExpression,
                                           int index,
                                           boolean hasComma) {

            visitor.addIdentificationVariables();
            visitor.addFunctionIdentifiers(queryBNF(expression, index));
        }

        @Override
        public CollectionExpression buildCollectionExpression(ConcatExpression expression) {
            CollectionExpression collectionExpression = visitor.getCollectionExpression(expression.getExpression());
            if (collectionExpression == null) {
                collectionExpression = expression.buildCollectionExpression();
            }
            return collectionExpression;
        }

        @Override
        public boolean canContinue(ConcatExpression expression,
                                   CollectionExpression collectionExpression,
                                   int index) {

            return false;
        }

        @Override
        public boolean hasDelimiterAfterIdentifier(ConcatExpression expression) {
            return expression.hasSpaceAfterIdentifier() ||
                   expression.hasLeftParenthesis();
        }

        @Override
        public int maxCollectionSize(ConcatExpression expression) {
            return Integer.MAX_VALUE;
        }

        @Override
        public int preExpressionLength(ConcatExpression expression) {
            return 0;
        }

        @Override
        public JPQLQueryBNF queryBNF(ConcatExpression expression, int index) {
            return visitor.getQueryBNF(expression.getEncapsulatedExpressionQueryBNFId());
        }

    }

    // Made static final for performance reasons.
    /**
     * This helpers handles adding proposals for {@link AbstractConditionalClause}.
     */
    protected static final class ConditionalClauseCollectionHelper extends AbstractConditionalClauseCollectionHelper<AbstractConditionalClause> {

        protected ConditionalClauseCollectionHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public CollectionExpression buildCollectionExpression(AbstractConditionalClause expression) {
            CollectionExpression collectionExpression = visitor.getCollectionExpression(expression.getConditionalExpression());
            if (collectionExpression == null) {
                collectionExpression = expression.buildCollectionExpression();
            }
            return collectionExpression;
        }

        @Override
        public boolean hasDelimiterAfterIdentifier(AbstractConditionalClause expression) {
            return expression.hasSpaceAfterIdentifier();
        }
    }

    // Made static final for performance reasons.
    protected static final class ConstrutorCollectionHelper
            extends AbstractVisitorHelper implements CollectionExpressionHelper<ConstructorExpression> {

        protected ConstrutorCollectionHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public void addAtTheEndOfChild(ConstructorExpression expression,
                                       CollectionExpression collectionExpression,
                                       int index,
                                       boolean hasComma,
                                       boolean virtualSpace) {

            // The only thing that is appendable is an arithmetic operator
            // Example: "SELECT e.name|"
            // Example: "SELECT e|"
            if (queryBNF(expression, index).handleAggregate()) {

                Expression child = collectionExpression.getChild(index);

                if ((index == 0) && !virtualSpace) {

                    if (visitor.areArithmeticSymbolsAppendable(child)) {
                        visitor.addArithmeticIdentifiers();
                    }
                }
                else {

                    if (visitor.areArithmeticSymbolsAppendable(child)) {
                        visitor.addArithmeticIdentifiers();
                    }

                    if (visitor.areComparisonSymbolsAppendable(child)) {
                        visitor.addComparisonIdentifiers(child);
                    }
                }
            }
        }

        @Override
        public void addIdentifier(ConstructorExpression expression, String identifier) {
            visitor.proposals.addIdentifier(identifier);
        }

        @Override
        public void addTheBeginningOfChild(ConstructorExpression expression,
                                           CollectionExpression collectionExpression,
                                           int index,
                                           boolean hasComma) {

            visitor.addIdentificationVariables(expression, IdentificationVariableType.ALL);
            visitor.addFunctionIdentifiers(ConstructorItemBNF.ID);
        }

        @Override
        public CollectionExpression buildCollectionExpression(ConstructorExpression expression) {
            CollectionExpression collectionExpression = visitor.getCollectionExpression(expression.getConstructorItems());
            if (collectionExpression == null) {
                collectionExpression = expression.buildCollectionExpression();
            }
            return collectionExpression;
        }

        @Override
        public boolean canContinue(ConstructorExpression expression,
                                   CollectionExpression collectionExpression,
                                   int index) {

            return false;
        }

        @Override
        public boolean hasDelimiterAfterIdentifier(ConstructorExpression expression) {
            return expression.hasLeftParenthesis();
        }

        @Override
        public int maxCollectionSize(ConstructorExpression expression) {
            return Integer.MAX_VALUE;
        }

        @Override
        public int preExpressionLength(ConstructorExpression expression) {
            if (expression.hasSpaceAfterNew()) {
                return expression.getClassName().length() + SPACE_LENGTH;
            }
            return expression.getClassName().length();
        }

        @Override
        public JPQLQueryBNF queryBNF(ConstructorExpression expression, int index) {
            return visitor.getQueryBNF(ConstructorItemBNF.ID);
        }
    }

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

        /**
         * Indicates if the visited {@link CollectionValuedPathExpression} is found within a
         * declaration expression.
         */
        protected boolean declaration;

        /**
         * Disposes of the internal data.
         */
        public void dispose() {
            declaration = false;
        }

        /**
         * Determines whether the visited path expression is found within a declaration expression.
         *
         * @return <code>true</code> if the visited {@link CollectionValuedPathExpression} is owned by
         * a {@link RangeVariableDeclaration}, which indicates it is used to define the "root" object;
         * <code>false</code> if it is not
         */
        public boolean isDeclaration() {
            return declaration;
        }

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

        @Override
        public void visit(RangeVariableDeclaration expression) {
            declaration = true;
        }
    }

    // Made static final for performance reasons.
    /**
     * The default implementation of {@link MappingCollector}, which simply returns an empty collection.
     */
    protected static final class DefaultMappingCollector implements MappingCollector {

        @Override
        public Collection<IMapping> buildProposals() {
            return Collections.emptyList();
        }
    }

    // Made static final for performance reasons.
    protected static final class DeleteClauseCollectionHelper
            extends AbstractVisitorHelper implements CollectionExpressionHelper<DeleteClause> {

        protected DeleteClauseCollectionHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public void addAtTheEndOfChild(DeleteClause expression,
                                       CollectionExpression collectionExpression,
                                       int index,
                                       boolean hasComma,
                                       boolean virtualSpace) {
        }

        @Override
        public void addIdentifier(DeleteClause expression, String identifier) {
            visitor.proposals.addIdentifier(identifier);
        }

        @Override
        public void addTheBeginningOfChild(DeleteClause expression,
                                           CollectionExpression collectionExpression,
                                           int index,
                                           boolean hasComma) {

            if (index == 0) {
                visitor.addEntities();
            }
        }

        @Override
        public CollectionExpression buildCollectionExpression(DeleteClause expression) {
            CollectionExpression collectionExpression = visitor.getCollectionExpression(expression.getRangeVariableDeclaration());
            if (collectionExpression == null) {
                collectionExpression = expression.buildCollectionExpression();
            }
            return collectionExpression;
        }

        @Override
        public boolean canContinue(DeleteClause expression,
                                   CollectionExpression collectionExpression,
                                   int index) {

            return false;
        }

        @Override
        public boolean hasDelimiterAfterIdentifier(DeleteClause expression) {
            return expression.hasSpaceAfterFrom();
        }

        @Override
        public int maxCollectionSize(DeleteClause expression) {
            return Integer.MAX_VALUE;
        }

        @Override
        public int preExpressionLength(DeleteClause expression) {
            return 0;
        }

        @Override
        public JPQLQueryBNF queryBNF(DeleteClause expression, int index) {
            return visitor.getQueryBNF(RangeVariableDeclarationBNF.ID);
        }
    }

    // Made static final for performance reasons.
    protected static final class DeleteClauseStatementHelper
            extends AbstractVisitorHelper implements StatementHelper<DeleteStatement> {

        protected DeleteClauseStatementHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public void addClauseProposals() {
            visitor.addIdentifier(DELETE_FROM);
        }

        @Override
        public void addInternalClauseProposals(DeleteStatement expression) {
            // Does not have internal clauses
        }

        @Override
        public Expression getClause(DeleteStatement expression) {
            return expression.getDeleteClause();
        }

        @Override
        public WhereClauseDeleteStatementHelper getNextHelper() {
            return visitor.getWhereClauseDeleteStatementHelper();
        }

        @Override
        public boolean hasClause(DeleteStatement expression) {
            return true;
        }

        @Override
        public boolean hasSpaceAfterClause(DeleteStatement expression) {
            return expression.hasSpaceAfterDeleteClause();
        }

        @Override
        public boolean isClauseComplete(DeleteStatement expression) {
            return visitor.isComplete(expression.getDeleteClause());
        }

        @Override
        public boolean isRequired() {
            return true;
        }
    }

    // Made static final for performance reasons.
    protected static final class DifferentComparisonFilter
            extends AnonymousExpressionVisitor implements Filter<Expression> {

        /**
         * Determines whether {@literal '<', '<=', '>=', '>'} are valid comparison operators.
         */
        protected boolean valid;

        @Override
        public boolean accept(Expression expression) {
            try {
                expression.accept(this);
                return valid;
            }
            finally {
                valid = false;
            }
        }

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

        @Override
        public void visit(IdentificationVariable expression) {
            valid = false;
        }
    }

    // Made static final for performance reasons.
    protected static final class DoubleEncapsulatedCollectionHelper
            extends AbstractVisitorHelper implements CollectionExpressionHelper<AbstractDoubleEncapsulatedExpression> {

        protected DoubleEncapsulatedCollectionHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public void addAtTheEndOfChild(AbstractDoubleEncapsulatedExpression expression,
                                       CollectionExpression collectionExpression,
                                       int index,
                                       boolean hasComma,
                                       boolean virtualSpace) {

            // The only thing that is appendable is an arithmetic operator
            // Example: "SELECT e.name|"
            // Example: "SELECT e|"
            if (queryBNF(expression, index).handleAggregate()) {

                Expression child = collectionExpression.getChild(index);

                if ((index == 0) && !virtualSpace) {

                    if (visitor.areArithmeticSymbolsAppendable(child)) {
                        visitor.addArithmeticIdentifiers();
                    }
                }
                else {

                    if (visitor.areArithmeticSymbolsAppendable(child)) {
                        visitor.addArithmeticIdentifiers();
                    }

                    if (visitor.areComparisonSymbolsAppendable(child)) {
                        visitor.addComparisonIdentifiers(child);
                    }
                }
            }
        }

        @Override
        public void addIdentifier(AbstractDoubleEncapsulatedExpression expression, String identifier) {
            visitor.proposals.addIdentifier(identifier);
            visitor.addIdentificationVariables();
            visitor.addFunctionIdentifiers(expression.getParent().findQueryBNF(expression));
        }

        @Override
        public void addTheBeginningOfChild(AbstractDoubleEncapsulatedExpression expression,
                                           CollectionExpression collectionExpression,
                                           int index,
                                           boolean hasComma) {

            visitor.addIdentificationVariables();
            visitor.addFunctionIdentifiers(queryBNF(expression, index));
        }

        @Override
        public CollectionExpression buildCollectionExpression(AbstractDoubleEncapsulatedExpression expression) {
            return expression.buildCollectionExpression();
        }

        @Override
        public boolean canContinue(AbstractDoubleEncapsulatedExpression expression,
                                   CollectionExpression collectionExpression,
                                   int index) {

            return false;
        }

        @Override
        public boolean hasDelimiterAfterIdentifier(AbstractDoubleEncapsulatedExpression expression) {
            return expression.hasSpaceAfterIdentifier() ||
                   expression.hasLeftParenthesis();
        }

        @Override
        public int maxCollectionSize(AbstractDoubleEncapsulatedExpression expression) {
            // Both MOD and NULLIF allows a fixed 2 encapsulated expressions
            return 2;
        }

        @Override
        public int preExpressionLength(AbstractDoubleEncapsulatedExpression expression) {
            return 0;
        }

        @Override
        public JPQLQueryBNF queryBNF(AbstractDoubleEncapsulatedExpression expression, int index) {
            return visitor.getQueryBNF(expression.parameterExpressionBNF(index));
        }
    }

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

        /**
         * Determines whether the visited {@link Expression} is being encapsulated or not.
         */
        protected boolean encapsulated;

        /**
         * Internal flag that prevent infinite recursion.
         */
        protected boolean visited;

        /**
         * Disposes of the internal data.
         */
        public void dispose() {
            encapsulated = false;
        }

        /**
         * Determines whether the visited {@link Expression} is being encapsulated or not.
         *
         * @return <code>true</code> if the visited {@link Expression} is within parenthesis;
         * <code>false</code> otherwise
         */
        public boolean isEncapsulated() {
            return encapsulated;
        }

        @Override
        protected void visit(Expression expression) {
            if (!visited) {
                visited = true;
                expression.getParent().accept(this);
                visited = false;
            }
        }

        @Override
        public void visit(SubExpression expression) {
            encapsulated = true;
        }
    }

    // Made static for performance reasons.
    /**
     * This builder populates a {@link QueryPosition} by traversing the valid portion of the JPQL
     * query. The position is the end of each {@link Expression}.
     * <p>
     * For instance, "SELECT e FROM Employee e O WHERE e.name = 'JPQL'", the valid fragment is
     * "SELECT e FROM Employee e", the positions will be:
     * <ul>
     * <li>JPQLExpression = 24</li>
     * <li>SelectStatement = 24</li>
     * <li>FromClause = 15</li>
     * <li>IdentificationVariableDeclaration = 10</li>
     * <li>RangeVariableDeclaration = 10</li>
     * <li>IdentificationVariable = 1</li>
     * </ul>
     */
    protected static class EndingQueryPositionBuilder
            extends AbstractVisitorHelper implements ExpressionVisitor {

        /**
         * This internal flag helps to determine if the {@link Expression} where the cursor is located
         * was flagged to be invalid. If so, this helps to determine how to handle the calculation of
         * the new position within the query.
         * <p>
         * For instance: "SELECT e FROM Employee e AS" has a bad expression wrapping the identifier
         * "AS", which is parsed as a result variable. In this case, the position would actually be
         * 2 within the bad expression. If the bad expression was something more complex than just a
         * single word, then that expression should not be included in the position.
         */
        protected boolean badExpression;

        /**
         * This is used to correct the length of an {@link Expression}
         */
        protected int correction;

        /**
         * The {@link Expression} containing the invalid fragment.
         */
        protected Expression invalidExpression;

        /**
         * The position of the cursor within the invalid expression.
         */
        protected int positionWithinInvalidExpression;

        /**
         * This {@link QueryPosition} has the position of each {@link Expression} within the valid
         * fragment of the JPQL query.
         */
        public QueryPosition queryPosition;

        /**
         * Indicates whether a virtual space should be added to the stack or not.
         */
        public boolean virtualSpace;

        protected EndingQueryPositionBuilder(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        /**
         * Disposes the internal data.
         */
        public void dispose() {
            correction                      = 0;
            virtualSpace                    = false;
            queryPosition                   = null;
            invalidExpression               = null;
            positionWithinInvalidExpression = -1;
        }

        /**
         * Returns the new {@link QueryPosition} that was created.
         *
         * @return
         */
        public QueryPosition getQueryPosition() {
            return queryPosition;
        }

        /**
         * Determines whether a virtual space should be added to the stack or not.
         *
         * @return <code>true</code> if a virtual space should be considered; <code>false</code> otherwise
         */
        public boolean hasVirtualSpace() {
            return virtualSpace;
        }

        /**
         * Prepares this visitor before visiting an {@link Expression}. {@link #dispose()} is called
         * after the visit operation is complete.
         *
         * @param invalidExpression The {@link Expression} containing the invalid fragment
         */
        public void prepare(Expression invalidExpression) {

            QueryPosition oldQueryPosition = visitor.queryPosition;

            this.invalidExpression = invalidExpression;
            this.positionWithinInvalidExpression = oldQueryPosition.getPosition(invalidExpression);
            this.queryPosition = new QueryPosition(oldQueryPosition.getPosition(invalidExpression.getParent()));
        }

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

        @Override
        public void visit(AbstractSchemaName expression) {

            if (badExpression) {
                correction = expression.getLength() - positionWithinInvalidExpression;
            }

            if (invalidExpression == expression) {
                queryPosition.setExpression(expression);
                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

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

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

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

        @Override
        public void visit(ArithmeticFactor expression) {

            if (!badExpression) {

                if (expression.hasExpression()) {
                    expression.getExpression().accept(this);
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

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

        @Override
        public void visit(BadExpression expression) {
            badExpression = true;
            expression.getExpression().accept(this);
            badExpression = false;
        }

        @Override
        public void visit(BetweenExpression expression) {

            if (badExpression) {

                if (!expression.hasExpression() &&
                    !expression.hasNot()        &&
                    positionWithinInvalidExpression <= 7 /* BETWEEN */) {

                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
            }
            else {

                if (expression.hasUpperBoundExpression()) {
                    expression.getUpperBoundExpression().accept(this);
                }
                else if (expression.hasLowerBoundExpression() &&
                        !expression.hasAnd()) {

                    expression.getLowerBoundExpression().accept(this);
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

        @Override
        public void visit(CaseExpression expression) {

            if (badExpression) {

                if (positionWithinInvalidExpression <= 4 /* CASE */) {
                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
            }
            else {

                if (!expression.hasEnd()) {

                    if (expression.hasElseExpression()) {
                        expression.getElseExpression().accept(this);
                    }
                    else if (expression.hasWhenClauses()) {
                        expression.getWhenClauses();
                    }
                    else if (expression.hasCaseOperand()) {
                        expression.getCaseOperand().accept(this);
                    }
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

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

        @Override
        public void visit(CollectionExpression expression) {

            if (!badExpression) {

                // First find the index of the child expression owning the invalid fragment
                int index = 0;

                for (Expression child : expression.children()) {
                    if (child.isAncestor(invalidExpression)) {
                        break;
                    }
                    index++;
                }

                // This visitor is not used for an invalid expression but for looking at the
                // end of an expression and the whitespace is owned by a parent expression
                if (index == expression.childrenSize()) {
                    index--;
                }

                // Now traverse the child
                Expression child = expression.getChild(index);
                child.accept(this);

                // Rather than marking the CollectionExpression as the Expression to visit
                // with the adjusted QueryPosition, the child that to the left of the invalid
                // expression will be used instead.
                // Example: "SELECT e FROM Employee e WHERE CONCAT(e.name, A|S a)" <- | is the cursor
                //          In this example, "CONCAT(e.name, AS a)" is wrapped with a BadExpression, but
                //          "CONCAT(e.name, " is actually valid so this will allow the new QueryPosition
                //          to be "inside" the CONCAT expression and the proposals will be available
                if (index > 0) {
                    Expression previousChild = expression.getChild(index - 1);

                    if (!visitor.isComplete(previousChild)) {
                        queryPosition.setExpression(previousChild);
                        queryPosition.addPosition(previousChild, previousChild.getLength());
                    }
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                // Adjust the length so it's within the collection expression
                // up to the position of the cursor
                int length = expression.toActualText(index + 1).length() - correction;
                queryPosition.addPosition(expression, length);

                // Now reset the correction so the parent expression does
                // not use the entire length of CollectionExpression
                correction = expression.getLength() - length;
            }
        }

        @Override
        public void visit(CollectionMemberDeclaration expression) {

            if (badExpression) {
                if (positionWithinInvalidExpression <= 2 /* IN */) {
                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
            }
            else {

                if (expression.hasIdentificationVariable()) {
                    expression.getIdentificationVariable().accept(this);
                }
                else if (expression.hasCollectionValuedPathExpression() &&
                        !expression.hasAs()) {

                    expression.getCollectionValuedPathExpression().accept(this);
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

        @Override
        public void visit(CollectionMemberExpression expression) {

            if (badExpression) {

                if (!expression.hasEntityExpression() &&
                    !expression.hasNot()              &&
                    positionWithinInvalidExpression <= 6 /* MEMBER */) {

                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
            }
            else {

                if (expression.hasCollectionValuedPathExpression()) {
                    expression.getCollectionValuedPathExpression().accept(this);
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

        @Override
        public void visit(CollectionValuedPathExpression expression) {

            if (badExpression) {
                correction = expression.getLength() - positionWithinInvalidExpression;
            }

            if (invalidExpression == expression) {
                queryPosition.setExpression(expression);
                queryPosition.addPosition(expression, positionWithinInvalidExpression);
            }
        }

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

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

        @Override
        public void visit(ConstructorExpression expression) {

            if (badExpression) {

                if (positionWithinInvalidExpression <= 3 /* NEW */) {
                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
            }
            else {

                if (expression.hasConstructorItems() &&
                   !expression.hasRightParenthesis()) {

                    expression.getConstructorItems().accept(this);
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

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

        @Override
        public void visit(DateTime expression) {

            if (!expression.isJDBCDate()) {
                if (badExpression) {
                    correction = expression.getLength() - positionWithinInvalidExpression;
                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
                else if (invalidExpression == expression) {
                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
            }
        }

        @Override
        public void visit(DeleteClause expression) {

            if (badExpression) {

                if (positionWithinInvalidExpression <= 6/* DELETE */) {
                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
            }
            else {

                if (expression.hasRangeVariableDeclaration()) {
                    expression.getRangeVariableDeclaration().accept(this);
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

        @Override
        public void visit(DeleteStatement expression) {

            if (!badExpression) {

                if (expression.hasWhereClause()) {
                    expression.getWhereClause().accept(this);
                }
                else {
                    expression.getDeleteClause().accept(this);
                    if (expression.hasSpaceAfterDeleteClause()) {
                        virtualSpace = true;
                    }
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

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

        @Override
        public void visit(EmptyCollectionComparisonExpression expression) {

            if (badExpression) {

                if (!expression.hasExpression() &&
                    !expression.hasNot()        &&
                    positionWithinInvalidExpression <= 5 /* EMPTY */) {

                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
            }
            else {
                if (invalidExpression == expression) {
                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
            }
        }

        @Override
        public void visit(EntityTypeLiteral expression) {

            if (badExpression) {
                correction = expression.getLength() - positionWithinInvalidExpression;
            }

            if (invalidExpression == expression) {
                queryPosition.setExpression(expression);
                queryPosition.addPosition(expression, positionWithinInvalidExpression);
            }
        }

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

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

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

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

        @Override
        public void visit(GroupByClause expression) {

            if (badExpression) {

                if (positionWithinInvalidExpression <= 5 /* GROUP */) {
                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
            }
            else {

                if (expression.hasGroupByItems()) {
                    expression.getGroupByItems().accept(this);
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

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

        @Override
        public void visit(IdentificationVariable expression) {

            if (badExpression) {
                correction = expression.getLength() - positionWithinInvalidExpression;
            }

            queryPosition.setExpression(expression);
            queryPosition.addPosition(expression, positionWithinInvalidExpression);
        }

        @Override
        public void visit(IdentificationVariableDeclaration expression) {

            if (!badExpression) {

                if (expression.hasJoins()) {
                    expression.getJoins().accept(this);
                }
                else if (expression.hasRangeVariableDeclaration()) {
                    expression.getRangeVariableDeclaration().accept(this);
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

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

        @Override
        public void visit(InExpression expression) {

            if (badExpression) {

                if (!expression.hasExpression() &&
                    positionWithinInvalidExpression <= 2 /* IN */) {

                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
            }
            else {

                if (expression.hasInItems() &&
                   !expression.hasRightParenthesis()) {

                    expression.getInItems();
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

        @Override
        public void visit(InputParameter expression) {

            if (!badExpression) {

                if (invalidExpression == expression) {
                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
            }
        }

        @Override
        public void visit(Join expression) {

            if (badExpression) {

                if (positionWithinInvalidExpression <= 4 /* JOIN */) {
                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
            }
            else {

                if (expression.hasOnClause()) {
                    expression.getOnClause().accept(this);
                }
                else if (expression.hasIdentificationVariable()) {
                    expression.getIdentificationVariable().accept(this);
                    if (expression.hasSpaceAfterIdentificationVariable()) {
                        virtualSpace = true;
                    }
                }
                else if (expression.hasJoinAssociationPath() &&
                        !expression.hasAs()) {

                    expression.getJoinAssociationPath().accept(this);
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

        @Override
        public void visit(JPQLExpression expression) {

            if (expression.hasQueryStatement()) {
                Expression queryStatement = expression.getQueryStatement();
                queryStatement.accept(this);
                queryPosition.addPosition(expression, queryStatement.getLength() - correction);
            }
            else {
                queryPosition.setExpression(expression);
                queryPosition.addPosition(expression, 0);
            }
        }

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

        @Override
        public void visit(KeywordExpression expression) {

            if (badExpression) {
                correction = expression.getLength() - positionWithinInvalidExpression;
                queryPosition.setExpression(expression);
                queryPosition.addPosition(expression, positionWithinInvalidExpression);
            }
            else if (invalidExpression == expression) {
                queryPosition.setExpression(expression);
                queryPosition.addPosition(expression, positionWithinInvalidExpression);
            }
        }

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

        @Override
        public void visit(LikeExpression expression) {

            if (badExpression) {

                if (!expression.hasStringExpression() &&
                    positionWithinInvalidExpression <= 4 /* LIKE */) {

                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
            }
            else {

                if (expression.hasEscapeCharacter()) {
                    expression.getEscapeCharacter().accept(this);
                }
                else if (expression.hasPatternValue() &&
                        !expression.hasEscape()) {

                    expression.getPatternValue().accept(this);
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

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

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

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

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

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

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

        @Override
        public void visit(NotExpression expression) {

            if (badExpression) {

                if (positionWithinInvalidExpression <= 3 /* NOT */) {
                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
            }
            else {

                if (expression.hasExpression()) {
                    expression.getExpression().accept(this);
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

        @Override
        public void visit(NullComparisonExpression expression) {

            if (badExpression) {

                if (!expression.hasExpression() &&
                   !expression.hasNot()         &&
                   positionWithinInvalidExpression <= 2) {

                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
            }
            else {

                if (expression.hasExpression()) {
                    expression.getExpression().accept(this);
                }

                queryPosition.setExpression(expression);
                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

        @Override
        public void visit(NullExpression expression) {

            if (!badExpression) {

                if (invalidExpression == expression) {
                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, 0);
                }
            }
        }

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

        @Override
        public void visit(NumericLiteral expression) {

            if (!badExpression) {

                if (invalidExpression == expression) {
                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
            }
        }

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

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

        @Override
        public void visit(OrderByClause expression) {

            if (badExpression) {

                if (positionWithinInvalidExpression <= 5 /* ORDER */) {
                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
            }
            else {

                if (expression.hasOrderByItems()) {
                    expression.getOrderByItems().accept(this);
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

        @Override
        public void visit(OrderByItem expression) {

            if (!badExpression) {

                if (expression.hasExpression()) {
                    expression.getExpression().accept(this);
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

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

        @Override
        public void visit(RangeVariableDeclaration expression) {

            if (!badExpression) {

                if (expression.hasIdentificationVariable()) {
                    expression.getIdentificationVariable().accept(this);
                }
                else if (!expression.hasAs()) {
                    expression.getRootObject().accept(this);
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

        @Override
        public void visit(ResultVariable expression) {

            if (badExpression) {

                // Special case for a result variable with nothing but the AS identifier
                if (!expression.hasResultVariable() &&
                     expression.hasAs() ||
                    !expression.hasSelectExpression()) {

                    correction = expression.getLength() - positionWithinInvalidExpression;

                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
            }
            else {

                if (expression.hasResultVariable()) {
                    expression.getResultVariable().accept(this);
                }
                else if (!expression.hasAs()) {
                    expression.getSelectExpression().accept(this);
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

        @Override
        public void visit(SelectClause expression) {

            if (badExpression) {

                if (positionWithinInvalidExpression <= 6 /* SELECT */) {
                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
            }
            else {

                if (expression.hasSelectExpression()) {
                    expression.getSelectExpression().accept(this);
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

        @Override
        public void visit(SelectStatement expression) {

            if (!badExpression) {

                if (expression.hasUnionClauses()) {
                    expression.getUnionClauses().accept(this);
                }
                else if (expression.hasOrderByClause()) {
                    expression.getOrderByClause().accept(this);
                    if (expression.hasSpaceBeforeUnion()) {
                        virtualSpace = true;
                    }
                }
                else if (expression.hasHavingClause()) {
                    expression.getHavingClause().accept(this);
                    if (expression.hasSpaceBeforeOrderBy()) {
                        virtualSpace = true;
                    }
                }
                else if (expression.hasGroupByClause()) {
                    expression.getGroupByClause().accept(this);
                    if (expression.hasSpaceAfterGroupBy()) {
                        virtualSpace = true;
                    }
                }
                else if (expression.hasWhereClause()) {
                    expression.getWhereClause().accept(this);
                    if (expression.hasSpaceAfterWhere()) {
                        virtualSpace = true;
                    }
                }
                else if (expression.hasFromClause()) {
                    expression.getFromClause().accept(this);
                    if (expression.hasSpaceAfterFrom()) {
                        virtualSpace = true;
                    }
                }
                else {
                    expression.getSelectClause().accept(this);
                    if (expression.hasSpaceAfterSelect()) {
                        virtualSpace = true;
                    }
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

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

        @Override
        public void visit(SimpleSelectClause expression) {

            if (!badExpression) {

                if (expression.hasSelectExpression()) {
                    expression.getSelectExpression().accept(this);
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

        @Override
        public void visit(SimpleSelectStatement expression) {

            if (!badExpression) {

                if (expression.hasHavingClause()) {
                    expression.getHavingClause().accept(this);
                }
                else if (expression.hasGroupByClause()) {
                    expression.getGroupByClause().accept(this);
                    if (expression.hasSpaceAfterGroupBy()) {
                        virtualSpace = true;
                    }
                }
                else if (expression.hasWhereClause()) {
                    expression.getWhereClause().accept(this);
                    if (expression.hasSpaceAfterWhere()) {
                        virtualSpace = true;
                    }
                }
                else if (expression.hasFromClause()) {
                    expression.getFromClause().accept(this);
                    if (expression.hasSpaceAfterFrom()) {
                        virtualSpace = true;
                    }
                }
                else {
                    expression.getSelectClause().accept(this);
                    if (expression.hasSpaceAfterSelect()) {
                        virtualSpace = true;
                    }
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

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

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

        @Override
        public void visit(StateFieldPathExpression expression) {

            if (badExpression) {
                correction = expression.getLength() - positionWithinInvalidExpression;
            }

            if (invalidExpression == expression) {
                queryPosition.setExpression(expression);
                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

        @Override
        public void visit(StringLiteral expression) {

            if (!badExpression) {

                if (invalidExpression == expression) {
                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
            }
        }

        @Override
        public void visit(SubExpression expression) {
            visitAbstractSingleEncapsulatedExpression(expression);
        }

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

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

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

        @Override
        public void visit(TreatExpression expression) {

            if (badExpression) {

                if (positionWithinInvalidExpression <= 5 /* TREAT */) {
                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
            }
            else {

                if (expression.hasEntityType() &&
                   !expression.hasRightParenthesis()) {

                    expression.getEntityType().accept(this);
                }
                else if (expression.hasCollectionValuedPathExpression() &&
                        !expression.hasAs()) {

                    expression.getCollectionValuedPathExpression().accept(this);
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

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

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

        @Override
        public void visit(UnknownExpression expression) {
            // Nothing to do, this is the expression that needs
            // to be handled by the valid portion of the JPQL query
        }

        @Override
        public void visit(UpdateClause expression) {

            if (badExpression) {

                if (positionWithinInvalidExpression <= 6 /* UPDATE */) {
                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
            }
            else {

                if (expression.hasUpdateItems()) {
                    expression.getUpdateItems().accept(this);
                }
                else if (expression.hasRangeVariableDeclaration()) {
                    expression.getRangeVariableDeclaration().accept(this);
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

        @Override
        public void visit(UpdateItem expression) {

            if (!badExpression) {

                if (expression.hasNewValue()) {
                    expression.getNewValue().accept(this);
                }
                else if (!expression.hasEqualSign() &&
                          expression.hasSpaceAfterStateFieldPathExpression()) {

                    expression.getStateFieldPathExpression().accept(this);
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

        @Override
        public void visit(UpdateStatement expression) {

            if (!badExpression) {

                if (expression.hasWhereClause()) {
                    expression.getWhereClause().accept(this);
                }
                else {
                    expression.getUpdateClause().accept(this);
                    if (expression.hasSpaceAfterUpdateClause()) {
                        virtualSpace = true;
                    }
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

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

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

        @Override
        public void visit(WhenClause expression) {

            if (badExpression) {

                if (positionWithinInvalidExpression <= 4 /* WHEN */) {
                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
            }
            else {

                if (expression.hasThenExpression()) {
                    expression.getThenExpression().accept(this);
                }
                else if (expression.hasWhenExpression() &&
                         expression.hasThen()) {

                    expression.getWhenExpression().accept(this);
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

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

        protected void visitAbstractConditionalClause(AbstractConditionalClause expression) {

            if (!badExpression) {

                if (expression.hasConditionalExpression()) {
                    expression.getConditionalExpression().accept(this);
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

        protected void visitAbstractDoubleEncapsulatedExpression(AbstractDoubleEncapsulatedExpression expression) {

            if (badExpression) {

                if (positionWithinInvalidExpression <= expression.getIdentifier().length()) {
                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
            }
            else {

                if (expression.hasSecondExpression() &&
                   !expression.hasRightParenthesis()) {

                    expression.getSecondExpression().accept(this);
                }
                else if (expression.hasFirstExpression() &&
                        !expression.hasSpaceAfterComma()) {

                    expression.getFirstExpression().accept(this);
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

        protected void visitAbstractFromClause(AbstractFromClause expression) {

            if (badExpression) {

                if (positionWithinInvalidExpression <= 4 /* FROM */) {
                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
            }
            else {

                if (expression.hasAsOfClause()) {
                    expression.getAsOfClause().accept(this);
                }
                else if (expression.hasHierarchicalQueryClause()) {

                    expression.getHierarchicalQueryClause().accept(this);

                    if (expression.hasSpaceAfterHierarchicalQueryClause()) {
                        virtualSpace = true;
                    }
                }
                else if (expression.hasDeclaration()) {

                    expression.getDeclaration().accept(this);

                    if (expression.hasSpaceAfterDeclaration()) {
                        virtualSpace = true;
                    }
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

        protected void visitAbstractSingleEncapsulatedExpression(AbstractSingleEncapsulatedExpression expression) {

            if (badExpression) {

                if (positionWithinInvalidExpression <= expression.getIdentifier().length()) {
                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
            }
            else {

                if (expression.hasEncapsulatedExpression() &&
                   !expression.hasRightParenthesis()) {

                    expression.getExpression().accept(this);
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

        protected void visitAbstractTripleEncapsulatedExpression(AbstractTripleEncapsulatedExpression expression) {

            if (badExpression) {

                if (positionWithinInvalidExpression <= expression.getIdentifier().length()) {
                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
            }
            else {

                if (expression.hasThirdExpression() &&
                   !expression.hasRightParenthesis()) {

                    expression.getThirdExpression().accept(this);
                }
                else if (expression.hasSecondExpression() &&
                        !expression.hasSecondComma()) {

                    expression.getSecondExpression().accept(this);
                }
                else if (expression.hasFirstExpression() &&
                        !expression.hasFirstComma()) {

                    expression.getFirstExpression().accept(this);
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }

        protected void visitCompoundExpression(CompoundExpression expression) {

            if (badExpression) {

                if (positionWithinInvalidExpression <= expression.getIdentifier().length() &&
                    !expression.hasLeftExpression()) {

                    queryPosition.setExpression(expression);
                    queryPosition.addPosition(expression, positionWithinInvalidExpression);
                }
            }
            else {

                if (expression.hasRightExpression()) {
                    expression.getRightExpression().accept(this);
                }

                if (queryPosition.getExpression() == null) {
                    queryPosition.setExpression(expression);
                }

                queryPosition.addPosition(expression, expression.getLength() - correction);
            }
        }
    }

    // Made static final for performance reasons.
    /**
     * This visitor determines whether a path expression can be resolved as a fully qualified enum
     * type and an enum constant.
     * <p>
     * The valid locations are:
     * <ul>
     * <li>{@link CollectionMemberExpression} : entity_or_value_expression (before <code><b>MEMBER</b></code> identifier);</li>
     * <li>{@link InExpression} : One of the items;</li>
     * <li>{@link CaseExpression} : The <code><b>ELSE</b> expression</code>;</li>
     * <li>{@link WhenClause} : The <code><b>WHEN</b></code> or <code><b>THEN</b></code> expressions;</li>
     * <li>{@link FunctionExpression} : One of the function items;</li>
     * <li>{@link ComparisonExpression} : The left or right expression if the comparison identifier
     *     is either <code><b>=</b></code> or <code><b>&lt;&gt;</b></code>;</li>
     * <li>{@link UpdateItem} : The new value;</li>
     * <li>{@link ConstructorExpression} : One of the constructor items;</li>
     * <li>{@link CoalesceExpression} : The expression at index 1 or greater;</li>
     * <li>{@link NullIfExpression} : The second expression;</li>
     * </ul>
     */
    protected static final class EnumVisitor extends AbstractExpressionVisitor {

        /**
         * The {@link AbstractPathExpression} being scanned for its location within the JPQL query.
         */
        protected AbstractPathExpression pathExpression;

        /**
         * Determines whether the path expression could potentially represent a fully qualified
         * enum constant, which is dictated by the location of the path expression within the query.
         * Only a few location allows an enum constant.
         */
        protected boolean valid;

        /**
         * Disposes of the internal data.
         */
        public void dispose() {
            valid = false;
            pathExpression = null;
        }

        /**
         * Determines whether the path expression could potentially represent a fully qualified
         * enum constant, which is dictated by the location of the path expression within the query.
         * Only a few location allows an enum constant.
         *
         * @return <code>true</code> if the path expression represents a enum constant;
         * <code>false</code> otherwise
         */
        public boolean isValid() {
            return valid;
        }

        @Override
        public void visit(CaseExpression expression) {
            valid = (pathExpression == expression.getElseExpression());
        }

        @Override
        public void visit(CoalesceExpression expression) {
            // TODO
            valid = (pathExpression == expression.getExpression());
        }

        @Override
        public void visit(CollectionMemberExpression expression) {
            valid = (pathExpression == expression.getEntityExpression());
        }

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

        @Override
        public void visit(ComparisonExpression expression) {
            String identifier = expression.getComparisonOperator();
            valid = ((identifier == EQUAL) || (identifier == DIFFERENT));
        }

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

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

        @Override
        public void visit(InExpression expression) {
            valid = (pathExpression != expression.getExpression());
        }

        @Override
        public void visit(NullIfExpression expression) {
            valid = (pathExpression == expression.getSecondExpression());
        }

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

        @Override
        public void visit(UpdateItem expression) {
            valid = (pathExpression == expression.getNewValue());
        }

        @Override
        public void visit(WhenClause expression) {
            valid = (pathExpression == expression.getThenExpression() ||
                     pathExpression == expression.getWhenExpression());
        }
    }

    // Made static final for performance reasons.
    /**
     * This {@link MappingCollector} returns the possible mappings (non-collection type or
     * collection type) from a managed type.
     */
    protected static final class FilteringMappingCollector implements MappingCollector {

        /**
         * The {@link Filter} used to filter out either the collection type properties or the non-
         * collection type properties.
         */
        protected final Filter<IMapping> filter;

        /**
         * This resolver is used to retrieve the managed type, which is the parent path of this one.
         */
        protected final Resolver resolver;

        /**
         * The suffix is used to determine if the mapping name needs to be filtered out or not.
         */
        protected final String suffix;

        /**
         * Creates a new <code>FilteringMappingCollector</code>.
         *
         * @param resolver This resolver is used to retrieve the managed type, which is the parent
         * path of this one
         * @param filter The filter used to filter out either the collection type properties or the
         * non-collection type properties
         * @param suffix The suffix is used to determine if the property name needs to be filtered out
         * or not
         */
        FilteringMappingCollector(Resolver resolver, Filter<IMapping> filter, String suffix) {
            super();
            this.filter   = filter;
            this.suffix   = suffix;
            this.resolver = resolver;
        }

        protected void addFilteredMappings(IManagedType managedType, List<IMapping> mappings) {

            Filter<IMapping> filter = buildFilter(suffix);

            for (IMapping mapping : managedType.mappings()) {
                if (filter.accept(mapping)) {
                    mappings.add(mapping);
                }
            }
        }

        protected Filter<IMapping> buildFilter(String suffix) {
            if (suffix.length() == 0) {
                return filter;
            }
            return new AndFilter<IMapping>(filter, buildMappingNameFilter(suffix));
        }

        protected Filter<IMapping> buildMappingNameFilter(final String suffix) {
            return new Filter<IMapping>() {
                @Override
                public boolean accept(IMapping mapping) {
                    return mapping.getName().startsWith(suffix);
                }
            };
        }

        @Override
        public Collection<IMapping> buildProposals() {

            IManagedType managedType = resolver.getManagedType();

            if (managedType == null) {
                return Collections.emptyList();
            }

            ArrayList<IMapping> mappings = new ArrayList<IMapping>();
            addFilteredMappings(managedType, mappings);
            return mappings;
        }
    }

    // Made static for performance reasons.
    protected static class FollowingClausesVisitor extends AbstractTraverseParentVisitor {

        /**
         * The JPQL identifier of the clause used to determine if there is any clause defined after it.
         */
        protected String afterIdentifier;

        /**
         * The JPQL identifier of the clause used to determine if there is any clause defined before it.
         */
        protected String beforeIdentifier;

        /**
         * Determines whether there is at least one clause defined after the clause defined by {@link #afterIdentifier}.
         */
        protected boolean hasFollowUpClauses;

        /**
         * Disposes of the internal data.
         */
        public void dispose() {
            afterIdentifier    = null;
            beforeIdentifier   = null;
            hasFollowUpClauses = false;
        }

        /**
         * Determines if the <code><b>FROM</b></code> clause has been defined or not. The end limit
         * of the check is also taken into consideration.
         *
         * @param expression The <code><b>SELECT</b></code> expression being scanned for what has been
         * defined between the range of clauses
         * @return <code>true</code> if the <code><b>FROM</b></code> clause is defined;
         * <code>false</code> otherwise
         */
        protected boolean hasFromClause(AbstractSelectStatement expression) {
            // No need to check if the check is after the clause itself
            return (afterIdentifier != FROM) && expression.hasFromClause();
        }

        @Override
        public void visit(SelectStatement expression) {

            if (afterIdentifier == SELECT) {

                if (beforeIdentifier == WHERE) {
                    hasFollowUpClauses = hasFromClause(expression);
                }
                else if (beforeIdentifier == GROUP_BY) {
                    hasFollowUpClauses = hasFromClause(expression) ||
                                         expression.hasWhereClause();
                }
                else if (beforeIdentifier == HAVING) {
                    hasFollowUpClauses = hasFromClause(expression)   ||
                                         expression.hasWhereClause() ||
                                         expression.hasGroupByClause();
                }
                else if (beforeIdentifier == ORDER_BY) {
                    hasFollowUpClauses = hasFromClause(expression)     ||
                                         expression.hasWhereClause()   ||
                                         expression.hasGroupByClause() ||
                                         expression.hasHavingClause();
                }
                else if (beforeIdentifier == null) {
                    hasFollowUpClauses = hasFromClause(expression)     ||
                                         expression.hasWhereClause()   ||
                                         expression.hasGroupByClause() ||
                                         expression.hasHavingClause()  ||
                                         expression.hasOrderByClause();
                }
                else {
                    hasFollowUpClauses = hasFromClause(expression);
                }
            }
            else if (afterIdentifier == FROM) {

                if (beforeIdentifier == GROUP_BY) {
                    hasFollowUpClauses = hasFromClause(expression) ||
                                         expression.hasWhereClause();
                }
                else if (beforeIdentifier == HAVING) {
                    hasFollowUpClauses = hasFromClause(expression)   ||
                                         expression.hasWhereClause() ||
                                         expression.hasGroupByClause();
                }
                else if (beforeIdentifier == ORDER_BY) {
                    hasFollowUpClauses = hasFromClause(expression)     ||
                                         expression.hasWhereClause()   ||
                                         expression.hasGroupByClause() ||
                                         expression.hasHavingClause();
                }
                else if (beforeIdentifier == null) {
                    hasFollowUpClauses = hasFromClause(expression)     ||
                                         expression.hasWhereClause()   ||
                                         expression.hasGroupByClause() ||
                                         expression.hasHavingClause()  ||
                                         expression.hasOrderByClause();
                }
                else {
                    hasFollowUpClauses = hasFromClause(expression);
                }
            }
            else if (afterIdentifier == WHERE) {

                if (beforeIdentifier == HAVING) {
                    hasFollowUpClauses = expression.hasGroupByClause();
                }
                else if (beforeIdentifier == ORDER_BY) {
                    hasFollowUpClauses = expression.hasGroupByClause() ||
                                         expression.hasHavingClause();
                }
                else if (beforeIdentifier == null) {
                    hasFollowUpClauses = expression.hasGroupByClause() ||
                                         expression.hasHavingClause()  ||
                                         expression.hasOrderByClause();
                }
            }
            else if (afterIdentifier == GROUP_BY) {

                if (beforeIdentifier == ORDER_BY) {
                    hasFollowUpClauses = expression.hasHavingClause();
                }
                else if (beforeIdentifier == null) {
                    hasFollowUpClauses = expression.hasHavingClause() ||
                                         expression.hasOrderByClause();
                }
            }
            else if (afterIdentifier == HAVING) {
                hasFollowUpClauses = expression.hasOrderByClause();
            }
            else {
                hasFollowUpClauses = hasFromClause(expression);
            }
        }

        @Override
        public void visit(SimpleFromClause expression) {
            expression.getParent().accept(this);
        }

        @Override
        public void visit(SimpleSelectStatement expression) {

            if (afterIdentifier == SELECT) {

                if (beforeIdentifier == WHERE) {
                    hasFollowUpClauses = hasFromClause(expression);
                }
                else if (beforeIdentifier == GROUP_BY) {
                    hasFollowUpClauses = hasFromClause(expression) ||
                                         expression.hasWhereClause();
                }
                else if (beforeIdentifier == HAVING) {
                    hasFollowUpClauses = hasFromClause(expression)   ||
                                         expression.hasWhereClause() ||
                                         expression.hasGroupByClause();
                }
                else if (beforeIdentifier == null) {
                    hasFollowUpClauses = hasFromClause(expression)     ||
                                         expression.hasWhereClause()   ||
                                         expression.hasGroupByClause() ||
                                         expression.hasHavingClause();
                }
            }
            else if (afterIdentifier == FROM) {

                if (beforeIdentifier == GROUP_BY) {
                    hasFollowUpClauses = hasFromClause(expression) ||
                                         expression.hasWhereClause();
                }
                else if (beforeIdentifier == HAVING) {
                    hasFollowUpClauses = hasFromClause(expression)   ||
                                         expression.hasWhereClause() ||
                                         expression.hasGroupByClause();
                }
                else if (beforeIdentifier == null) {
                    hasFollowUpClauses = hasFromClause(expression)     ||
                                         expression.hasWhereClause()   ||
                                         expression.hasGroupByClause() ||
                                         expression.hasHavingClause();
                }
            }
            else if (afterIdentifier == WHERE) {

                if (beforeIdentifier == HAVING) {
                    hasFollowUpClauses = expression.hasGroupByClause();
                }
                else if (beforeIdentifier == null) {
                    hasFollowUpClauses = expression.hasGroupByClause() ||
                                         expression.hasHavingClause();
                }
            }
        }
    }

    // Made static final for performance reasons.
    protected static final class FollowingInvalidExpressionVisitor extends AbstractTraverseParentVisitor {

        /**
         * Enclosing visitor instance.
         */
        protected final AbstractContentAssistVisitor visitor;

        /**
         * The {@link Expression} used to determine if it follows an invalid fragment or not.
         */
        protected Expression expression;

        /**
         * Determines whether the visited {@link Expression} is preceded by an invalid expression.
         */
        protected boolean followingInvalidExpression;

        protected FollowingInvalidExpressionVisitor(AbstractContentAssistVisitor visitor) {
            super();
            this.visitor = visitor;
        }

        /**
         * Disposes of the internal data.
         */
        public void dispose() {
            expression = null;
            followingInvalidExpression = false;
        }

        /**
         * Determines whether the visited {@link Expression} is preceded by an invalid expression.
         *
         * @return <code>true</code> if the visited {@link Expression} is part of a collection of
         * expressions and an invalid expression precede it; <code>false</code> otherwise
         */
        public boolean isFollowingInvalidExpression() {
            return followingInvalidExpression;
        }

        @Override
        public void visit(CollectionExpression expression) {

            int index = expression.childrenSize();

            // Find the index of the expression for which the tree is been visited
            while (--index >= 0) {
                Expression child = expression.getChild(index);

                if (child == this.expression) {
                    break;
                }
            }

            // Check to see if an expression before the index is invalid
            while (--index >= 0) {
                Expression child = expression.getChild(index);
                followingInvalidExpression = visitor.isInvalidExpression(child);

                if (followingInvalidExpression) {
                    index = -1;
                }
            }
        }

        @Override
        protected void visit(Expression expression) {
            this.expression = expression;
            super.visit(expression);
        }
    }

    // Made static for performance reasons.
    protected static class FromClauseCollectionHelper
            extends AbstractVisitorHelper implements CollectionExpressionHelper<AbstractFromClause> {

        protected FromClauseCollectionHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public void addAtTheEndOfChild(AbstractFromClause expression,
                                       CollectionExpression collectionExpression,
                                       int index,
                                       boolean hasComma,
                                       boolean virtualSpace) {

            // At the end of a range variable declaration, JOIN clauses can be added
            // Example: "SELECT e FROM Employee e |"
            // Example: "SELECT e FROM Employee e, Address a |"
            if (((index == 0) || hasComma) && virtualSpace) {
                // "... JOIN e.mananager m |" <- Valid to add JOIN identifiers
                // "... JOIN e.mananager m ON e.name |" <- Invalid to add JOIN identifiers
                if (visitor.isComplete(collectionExpression.getChild(0))) {
                    visitor.addJoinIdentifiers();
                    visitor.addIdentifier(ON);
                }
            }
            // Special case to handle a range variable declaration that can also
            // be either the beginning of the following clauses
            else {
                 boolean end = (index + 1 == collectionExpression.childrenSize());

                 if ((index > 0) && end && !hasComma) {

                    int position = visitor.queryPosition.getPosition();

                    if (!visitor.hasClausesDefinedBetween(expression, FROM, HAVING)) {
                        visitor.addCompositeIdentifier(GROUP_BY, 4 /* GROUP - 1 */);
                    }

                    if (!visitor.hasClausesDefinedBetween(expression, FROM, ORDER_BY)) {
                        visitor.addCompositeIdentifier(ORDER_BY, 4 /* ORDER - 1 */);
                    }
                 }
            }
        }

        @Override
        public void addIdentifier(AbstractFromClause expression, String identifier) {
            visitor.proposals.addIdentifier(identifier);
        }

        @Override
        public void addTheBeginningOfChild(AbstractFromClause expression,
                                           CollectionExpression collectionExpression,
                                           int index,
                                           boolean hasComma) {

            // 1. At the beginning of the FROM declaration, entities are valid proposals
            // 2. To be valid elsewhere, the declarations have to be separated by a comma
            //    "SELECT e FROM Employee e W|" <- entity names are not valid proposals, only 'WHERE' is
            if ((index == 0) || hasComma) {
                visitor.addEntities();
            }
            // In any other case, the JOIN identifiers are the only valid choices
            // "SELECT e FROM Employee e J|" <- only 'JOIN' and 'JOIN FETCH' are valid proposals
            else if ((index > 0) && !hasComma) {
                visitor.addJoinIdentifiers();
            }

            // The identifier for a collection member declaration can only be added
            // after the first declaration, as long as there is a comma before it
            // "SELECT e FROM Employee e, |" <- 'IN' is a valid proposal
            // "SELECT e FROM Employee e, I|" <- 'IN' is a valid proposal
            // "SELECT e FROM Employee e I|" <- 'IN' is NOT a valid proposal
            if ((index > 0) && hasComma) {
                visitor.addIdentifier(IN);
            }
        }

        @Override
        public CollectionExpression buildCollectionExpression(AbstractFromClause expression) {
            CollectionExpression collectionExpression = visitor.getCollectionExpression(expression.getDeclaration());
            if (collectionExpression == null) {
                collectionExpression = expression.buildCollectionExpression();
            }
            return collectionExpression;
        }

        @Override
        public boolean canContinue(AbstractFromClause expression,
                                   CollectionExpression collectionExpression,
                                   int index) {

            return true;
        }

        @Override
        public boolean hasDelimiterAfterIdentifier(AbstractFromClause expression) {
            return expression.hasSpaceAfterFrom();
        }

        @Override
        public int maxCollectionSize(AbstractFromClause expression) {
            return Integer.MAX_VALUE;
        }

        @Override
        public int preExpressionLength(AbstractFromClause expression) {
            return 0;
        }

        @Override
        public JPQLQueryBNF queryBNF(AbstractFromClause expression, int index) {
            return visitor.getQueryBNF(expression.getDeclarationQueryBNFId());
        }
    }

    // Made static for performance reasons.
    protected static class FromClauseStatementHelper extends AbstractFromClauseStatementHelper<SelectStatement> {

        protected FromClauseStatementHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public WhereClauseSelectStatementHelper getNextHelper() {
            return visitor.getWhereClauseSelectStatementHelper();
        }
    }

    // Made static final for performance reasons.
    protected static final class GroupByClauseCollectionHelper
            extends AbstractVisitorHelper implements CollectionExpressionHelper<GroupByClause> {

        protected GroupByClauseCollectionHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public void addAtTheEndOfChild(GroupByClause expression,
                                       CollectionExpression collectionExpression,
                                       int index,
                                       boolean hasComma,
                                       boolean virtualSpace) {
        }

        @Override
        public void addIdentifier(GroupByClause expression, String identifier) {
            visitor.proposals.addIdentifier(identifier);
        }

        @Override
        public void addTheBeginningOfChild(GroupByClause expression,
                                           CollectionExpression collectionExpression,
                                           int index,
                                           boolean hasComma) {

            if ((index == 0) || hasComma) {
                visitor.addFunctionIdentifiers(GroupByItemBNF.ID);
                visitor.addIdentificationVariables();
            }
        }

        @Override
        public CollectionExpression buildCollectionExpression(GroupByClause expression) {
            CollectionExpression collectionExpression = visitor.getCollectionExpression(expression.getGroupByItems());
            if (collectionExpression == null) {
                collectionExpression = expression.buildCollectionExpression();
            }
            return collectionExpression;
        }

        @Override
        public boolean canContinue(GroupByClause expression,
                                   CollectionExpression collectionExpression,
                                   int index) {

            return false;
        }

        @Override
        public boolean hasDelimiterAfterIdentifier(GroupByClause expression) {
            return expression.hasSpaceAfterGroupBy();
        }

        @Override
        public int maxCollectionSize(GroupByClause expression) {
            return Integer.MAX_VALUE;
        }

        @Override
        public int preExpressionLength(GroupByClause expression) {
            return 0;
        }

        @Override
        public JPQLQueryBNF queryBNF(GroupByClause expression, int index) {
            return visitor.getQueryBNF(GroupByItemBNF.ID);
        }
    }

    // Made static final for performance reasons.
    protected static final class GroupByClauseStatementHelper extends AbstractGroupByClauseStatementHelper<SelectStatement> {

        protected GroupByClauseStatementHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public HavingClauseStatementHelper getNextHelper() {
            return visitor.getHavingClauseStatementHelper();
        }
    }

    // Made static final for performance reasons.
    protected static final class HavingClauseStatementHelper extends AbstractHavingClauseStatementHelper<SelectStatement> {

        protected HavingClauseStatementHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public OrderByClauseStatementHelper getNextHelper() {
            return visitor.getOrderByClauseStatementHelper();
        }

        @Override
        public boolean hasSpaceAfterClause(SelectStatement expression) {
            return expression.hasSpaceBeforeOrderBy();
        }
    }

    // Made static for performance reasons.
    /**
     * The various ways of retrieving identification variables from the declaration expression.
     */
    protected static enum IdentificationVariableType {

        /**
         * Retrieves all the identification variables declared in the declaration portion of the
         * expression, which is either in the <b>FROM</b> clause of a <b>SELECT</b> query or
         * <b>DELETE</b> query or in the <b>UPDATE</b> query.
         */
        ALL {


            @Override
            protected boolean add(AbstractContentAssistVisitor contentAssist,
                                  Declaration declaration,
                               Expression expression) {

                if (declaration.getType() == Type.RANGE) {
                    contentAssist.addRangeIdentificationVariable(declaration.getVariableName());
                }
                else {
                    contentAssist.addIdentificationVariable(declaration.getVariableName());
                }

                for (Join join : declaration.getJoins()) {

                    String variableName = contentAssist.queryContext.literal(
                        join.getIdentificationVariable(),
                        LiteralType.IDENTIFICATION_VARIABLE
                    );

                    contentAssist.addIdentificationVariable(variableName);
                }

                return false;
            }
        },

        /**
         * Only retrieves the identification variables that map a path expression defined in a
         * <b>JOIN</b> expression or in a <b>IN</b> expression.
         */
        COLLECTION {


            @Override
            protected boolean add(AbstractContentAssistVisitor contentAssist,
                                  Declaration declaration,
                               Expression expression) {

                contentAssist.addIdentificationVariable(declaration.getVariableName());

                for (Join join : declaration.getJoins()) {

                    String variableName = contentAssist.queryContext.literal(
                        join.getIdentificationVariable(),
                        LiteralType.IDENTIFICATION_VARIABLE
                    );

                    contentAssist.addIdentificationVariable(variableName);
                }

                return false;
            }
        },

        /**
         * Only retrieves the identification variables that have been declared to the left of the
         * expression requested them, both range and collection type variables are collected.
         */
        LEFT {


            @Override
            protected boolean add(AbstractContentAssistVisitor contentAssist,
                                  Declaration declaration,
                               Expression expression) {

                boolean shouldStop = declaration.getDeclarationExpression().isAncestor(expression);

                if (shouldStop && !declaration.getJoins().contains(expression)) {
                    return true;
                }

                if (declaration.getType() == Type.RANGE) {
                    contentAssist.addRangeIdentificationVariable(declaration.getVariableName());
                }
                else {
                    contentAssist.addIdentificationVariable(declaration.getVariableName());
                }

                for (Join join : declaration.getJoins()) {

                    if (join.isAncestor(expression)) {
                        return true;
                    }

                    String variableName = contentAssist.queryContext.literal(
                        join.getIdentificationVariable(),
                        LiteralType.IDENTIFICATION_VARIABLE
                    );

                    contentAssist.addIdentificationVariable(variableName);
                }

                return false;
            }
        },

        /**
         * Only retrieves the identification variables that map a path expression defined in a
         * <b>JOIN</b> expression or in a <b>IN</b> expression but that have been declared to the
         * left of the expression requested them.
         */
        LEFT_COLLECTION {


            @Override
            protected boolean add(AbstractContentAssistVisitor contentAssist,
                                  Declaration declaration,
                               Expression expression) {

                boolean shouldStop = declaration.getDeclarationExpression().isAncestor(expression);

                if (shouldStop && declaration.getJoins().contains(expression)) {
                    return true;
                }

                if (!shouldStop && (declaration.getType() == Type.COLLECTION)) {
                    contentAssist.addIdentificationVariable(declaration.getVariableName());
                }
                else {

                    for (Join join : declaration.getJoins()) {

                        if (join.isAncestor(expression)) {
                            return true;
                        }

                        String variableName = contentAssist.queryContext.literal(
                            join.getIdentificationVariable(),
                            LiteralType.IDENTIFICATION_VARIABLE
                        );

                        contentAssist.addIdentificationVariable(variableName);
                    }
                }

                return false;
            }
        },

        /**
         * Simply indicates the identification variables should not be collected.
         */
        NONE {


            @Override
            protected boolean add(AbstractContentAssistVisitor contentAssist,
                                  Declaration declaration,
                               Expression expression) {

                // Nothing to do, stop immediately
                return true;
            }
        };

        /**
         * Adds the identification variables defined in the given {@link Declaration}.
         *
         * @param contentAssist Backpointer to the content assist class
         * @param declaration The {@link Declaration} in the order they are declared in the declaration clause
         * @param expression The {@link Expression} being visited, which can help to determine when to
         * stop collecting identification variables
         */
        protected abstract boolean add(AbstractContentAssistVisitor contentAssist,
                                       Declaration declaration,
                                       Expression expression);
    }

    // Made static for performance reasons.
    /**
     * This visitor is used when a clause or a compound expression was parsed with a collection of
     * expressions representing an invalid fragment.
     * <p>
     * Example: <code>SELECT e FROM Employee e GROUP B</code>
     * <p>
     * In this example, the <code><b>FROM</b></code> clause contains a collection of two
     * identification variable declarations, in a valid query, it would be separated by a comma, but
     * this one just means it's incomplete and "GROUP B" is the beginning of the <code><b>GROUP BY</b></code>
     * clause.
     */
    protected static class IncompleteCollectionExpressionVisitor extends AbstractExpressionVisitor {

        /**
         * The clause being visited, which is marked by its JPQL identifier.
         */
        protected String clause;

        /**
         * Determines whether an {@link Expression} that was visited is complete or if some part is missing.
         */
        protected boolean complete;

        /**
         * This flag is used to make sure only the last expression in a collection is tested. A single
         * expression cannot be used to check the "completeness".
         */
        protected boolean insideCollection;

        /**
         * Returns the list of identifiers for the clauses following the given identifier.
         *
         * @param afterIdentifier The JPQL identifier of the clause for which the list of following
         * clauses is built
         * @return The list of JPQL identifiers defining the clauses following the clause specified
         * by the given identifier
         */
        protected List<String> compositeIdentifiersAfter(String afterIdentifier) {

            if (clause == FROM) {
                return CollectionTools.list(GROUP_BY, ORDER_BY);
            }

            if (clause == WHERE) {
                return CollectionTools.list(GROUP_BY, ORDER_BY);
            }

            if (clause == HAVING) {
                return CollectionTools.list(ORDER_BY);
            }

            return new LinkedList<String>();
        }

        /**
         * Disposes of the internal data.
         */
        public void dispose() {
            complete = false;
        }

        /**
         * Determines whether an {@link Expression} that was visited is complete or if some part is missing.
         *
         * @return <code>true</code> if the visited {@link Expression} is grammatically complete;
         * <code>false</code> if it is incomplete
         */
        public boolean isComplete() {
            return complete;
        }

        /**
         * Determines whether the given JPQL fragment, which is the parsed text of the expression
         * invalid collection expression or the portion of it based on the cursor position within the
         * collection, is a composite identifier or not.
         *
         * @param clause The JPQL identifier of the clause having the collection of expressions
         * @param fragment The parsed text of the expression to determine if it's the beginning of the
         * composite identifier or not. The fragment is all lower case characters
         */
        protected boolean isPossibleCompositeIdentifier(String clause, String fragment) {

            for (String identifier : compositeIdentifiersAfter(clause)) {
                if (identifier.toLowerCase(Locale.ROOT).startsWith(fragment)) {
                    return true;
                }
            }

            return false;
        }

        @Override
        public void visit(CollectionExpression expression) {

            int lastIndex = expression.childrenSize() - 1;
            insideCollection = true;

            if (!expression.hasComma(lastIndex - 1)) {
                expression.getChild(lastIndex).accept(this);
            }

            insideCollection = false;
        }

        @Override
        public void visit(FromClause expression) {
            clause = FROM;
            expression.getDeclaration().accept(this);
            clause = null;
        }

        @Override
        public void visit(GroupByClause expression) {
            clause = GROUP_BY;
            expression.getGroupByItems().accept(this);
            clause = null;
        }

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

        @Override
        public void visit(IdentificationVariable expression) {
            complete = true;
        }

        @Override
        public void visit(IdentificationVariableDeclaration expression) {
            if (insideCollection && !expression.hasJoins()) {
                expression.getRangeVariableDeclaration().accept(this);
            }
        }

        @Override
        public void visit(OrderByClause expression) {
            clause = ORDER_BY;
            expression.getOrderByItems().accept(this);
            clause = null;
        }

        @Override
        public void visit(RangeVariableDeclaration expression) {

            if (insideCollection) {

                // The "root" object could be the first identifier of a composite identifier
                // (eg: GROUP) and the identification variable is 'B'
                complete = !expression.hasAs() && !expression.hasIdentificationVariable();

                // Special case for composite identifiers
                if (!complete) {
                    String fragment = expression.toParsedText().toLowerCase(Locale.ROOT);
                    complete = isPossibleCompositeIdentifier(clause, fragment);
                }
            }
        }

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

    // Made static final for performance reasons.
    /**
     * This visitor determines if the visited {@link Expression} is one of the two that represents
     * an invalid expression.
     */
    protected static final class InvalidExpressionVisitor extends AbstractExpressionVisitor {

        /**
         * The invalid {@link Expression}, which is either {@link UnknownExpression} or {@link BadExpression}.
         */
        protected Expression expression;

        /**
         * Disposes of the internal data.
         */
        public void dispose() {
            expression = null;
        }

        /**
         * Determines whether the visited {@link Expression} represents an invalid fragment.
         *
         * @return <code>true</code> if the {@link Expression} is an invalid fragment;
         * <code>false</code> otherwise
         */
        public boolean isInvalid() {
            return expression != null;
        }

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

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

    // Made static final for performance reasons.
    protected static final class JoinCollectionHelper
            extends AbstractVisitorHelper implements CollectionExpressionHelper<IdentificationVariableDeclaration> {

        protected JoinCollectionHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public void addAtTheEndOfChild(IdentificationVariableDeclaration expression,
                                       CollectionExpression collectionExpression,
                                       int index,
                                       boolean hasComma,
                                       boolean virtualSpace) {
        }

        @Override
        public void addIdentifier(IdentificationVariableDeclaration expression, String identifier) {
            visitor.proposals.addIdentifier(identifier);
        }

        @Override
        public void addTheBeginningOfChild(IdentificationVariableDeclaration expression,
                                           CollectionExpression collectionExpression,
                                           int index,
                                           boolean hasComma) {

            visitor.addJoinIdentifiers();
        }

        @Override
        public CollectionExpression buildCollectionExpression(IdentificationVariableDeclaration expression) {
            CollectionExpression collectionExpression = visitor.getCollectionExpression(expression.getJoins());
            if (collectionExpression == null) {
                collectionExpression = expression.buildCollectionExpression();
            }
            return collectionExpression;
        }

        @Override
        public boolean canContinue(IdentificationVariableDeclaration expression,
                                   CollectionExpression collectionExpression,
                                   int index) {

            return false;
        }

        @Override
        public boolean hasDelimiterAfterIdentifier(IdentificationVariableDeclaration expression) {
            return expression.hasSpace();
        }

        @Override
        public int maxCollectionSize(IdentificationVariableDeclaration expression) {
            return Integer.MAX_VALUE;
        }

        @Override
        public int preExpressionLength(IdentificationVariableDeclaration expression) {
            return expression.getRangeVariableDeclaration().getLength();
        }

        @Override
        public JPQLQueryBNF queryBNF(IdentificationVariableDeclaration expression, int index) {
            return visitor.getQueryBNF(InternalJoinBNF.ID);
        }
    }

    // Made static for performance reasons.
    /**
     * A collector is responsible to retrieve the possible proposals by using the mappings that can
     * complete a path expression.
     */
    protected static interface MappingCollector {

        /**
         * Retrieves the possible proposals that can be used to complete a path expression based on
         * the position of the cursor.
         *
         * @return The possible proposals
         */
        Collection<IMapping> buildProposals();
    }

    // Made static final for performance reasons.
    /**
     * This visitor is responsible to create the right {@link Filter} based on the type of the {@link Expression}.
     */
    protected static final class MappingFilterBuilder extends AbstractTraverseParentVisitor {

        /**
         * Enclosing visitor instance.
         */
        protected final AbstractContentAssistVisitor visitor;

        /**
         * The {@link Filter} that will filter the various type of {@link IMapping IMappings} based
         * on the location of the of the path expression within the JPQL query.
         */
        protected Filter<IMapping> filter;

        protected MappingFilterBuilder(AbstractContentAssistVisitor visitor) {
            super();
            this.visitor = visitor;
        }

        /**
         * Disposes of the internal data.
         */
        public void dispose() {
            filter = null;
        }

        @Override
        public void visit(AbsExpression expression) {
            filter = visitor.getMappingPropertyFilter();
        }

        @Override
        public void visit(AvgFunction expression) {
            filter = visitor.getMappingPropertyFilter();
        }

        @Override
        public void visit(BetweenExpression expression) {
            filter = visitor.getMappingPropertyFilter();
        }

        @Override
        public void visit(CoalesceExpression expression) {
            filter = visitor.getMappingPropertyFilter();
        }

        @Override
        public void visit(CollectionMemberDeclaration expression) {
            filter = visitor.getMappingCollectionFilter();
        }

        @Override
        public void visit(CollectionValuedPathExpression expression) {
            filter = visitor.getMappingCollectionFilter();
        }

        @Override
        public void visit(ConcatExpression expression) {
            filter = visitor.getMappingPropertyFilter();
        }

        @Override
        public void visit(CountFunction expression) {
            filter = visitor.getMappingPropertyFilter();
        }

        @Override
        public void visit(EmptyCollectionComparisonExpression expression) {
            filter = visitor.getMappingCollectionFilter();
        }

        @Override
        public void visit(FunctionExpression expression) {
            filter = visitor.getMappingPropertyFilter();
        }

        @Override
        public void visit(HavingClause expression) {
            // No need to filter, everything is allowed
            // Example: SELECT e FROM Employee e WHERE e.|
            //          1. Could become 'e.name = 'JPQL''
            //          2. Could become 'e.employees IS NOT NULL'
            //          3. Could become e.address.zipcode = 27519
            filter = NullFilter.instance();
        }

        @Override
        public void visit(Join expression) {
            filter = visitor.getMappingCollectionFilter();
        }

        @Override
        public void visit(JPQLExpression expression) {
            filter = visitor.getMappingPropertyFilter();
        }

        @Override
        public void visit(LengthExpression expression) {
            filter = visitor.getMappingPropertyFilter();
        }

        @Override
        public void visit(LocateExpression expression) {
            filter = visitor.getMappingPropertyFilter();
        }

        @Override
        public void visit(LowerExpression expression) {
            filter = visitor.getMappingPropertyFilter();
        }

        @Override
        public void visit(MaxFunction expression) {
            filter = visitor.getMappingPropertyFilter();
        }

        @Override
        public void visit(MinFunction expression) {
            filter = visitor.getMappingPropertyFilter();
        }

        @Override
        public void visit(ModExpression expression) {
            filter = visitor.getMappingPropertyFilter();
        }

        @Override
        public void visit(NullComparisonExpression expression) {
            filter = visitor.getMappingPropertyFilter();
        }

        @Override
        public void visit(OnClause expression) {
            // No need to filter, everything is allowed
            // Example: SELECT e FROM Employee e WHERE e.|
            //          1. Could become 'e.name = 'JPQL''
            //          2. Could become 'e.employees IS NOT NULL'
            //          3. Could become e.address.zipcode = 27519
            filter = NullFilter.instance();
        }

        @Override
        public void visit(SizeExpression expression) {
            filter = visitor.getMappingCollectionFilter();
        }

        @Override
        public void visit(SqrtExpression expression) {
            filter = visitor.getMappingPropertyFilter();
        }

        @Override
        public void visit(SubstringExpression expression) {
            filter = visitor.getMappingPropertyFilter();
        }

        @Override
        public void visit(SumFunction expression) {
            filter = visitor.getMappingPropertyFilter();
        }

        @Override
        public void visit(TreatExpression expression) {
            filter = visitor.getMappingCollectionFilter();
        }

        @Override
        public void visit(TrimExpression expression) {
            filter = visitor.getMappingPropertyFilter();
        }

        @Override
        public void visit(UpperExpression expression) {
            filter = visitor.getMappingPropertyFilter();
        }

        @Override
        public void visit(WhenClause expression) {
            // No need to filter, everything is allowed
            // Example: SELECT e FROM Employee e WHERE e.|
            //          1. Could become 'e.name = 'JPQL''
            //          2. Could become 'e.employees IS NOT NULL'
            //          3. Could become e.address.zipcode = 27519
            filter = NullFilter.instance();
        }

        @Override
        public void visit(WhereClause expression) {
            // No need to filter, everything is allowed
            // Example: SELECT e FROM Employee e WHERE e.|
            //          1. Could become 'e.name = 'JPQL''
            //          2. Could become 'e.employees IS NOT NULL'
            //          3. Could become e.address.zipcode = 27519
            filter = NullFilter.instance();
        }
    }

    // Made static final for performance reasons.
    /**
     * This {@link Filter} is responsible to filter out the mappings that can't have their type
     * assignable to the one passed in.
     */
    protected static final class MappingTypeFilter
            extends AbstractVisitorHelper implements Filter<IMapping> {

        /**
         * The type used to determine if the mapping's type is a valid type.
         */
        protected final IType type;

        /**
         * Creates a new <code>MappingTypeFilter</code>.
         *
         * @param type The type used to determine if the mapping's type is a valid type
         */
        MappingTypeFilter(IType type, AbstractContentAssistVisitor visitor) {
            super(visitor);
            this.type = type;
        }

        @Override
        public boolean accept(IMapping value) {

            // A reference mapping always can be used for further traversal
            if (value.isRelationship() &&
               !value.isCollection()) {

                return true;
            }

            // Determine if it's assignable to the desired type
            IType mappingType = value.getType();
            mappingType = visitor.queryContext.getTypeHelper().convertPrimitive(mappingType);
            return mappingType.isAssignableTo(type);
        }
    }

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

        /**
         * The {@link NotExpression} if it is the {@link Expression} being visited otherwise <code>null</code>.
         */
        protected NotExpression expression;

        /**
         * Disposes of the internal data.
         */
        public void dispose() {
            expression = null;
        }

        /**
         * Determines whether the {@link Expression} being visited is {@link NotExpression} or not.
         *
         * @return <code>true</code> if the {@link Expression} is {@link NotExpression};
         *  <code>null</code> otherwise
         */
        public boolean isNotExpression() {
            return expression != null;
        }

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

    // Made static final for performance reasons.
    protected static final class OrderByClauseCollectionHelper
            extends AbstractVisitorHelper implements CollectionExpressionHelper<AbstractOrderByClause> {

        protected OrderByClauseCollectionHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public void addAtTheEndOfChild(AbstractOrderByClause expression,
                                       CollectionExpression collectionExpression,
                                       int index,
                                       boolean hasComma,
                                       boolean virtualSpace) {

            OrderByItem item = (OrderByItem) collectionExpression.getChild(index);

            if (item.getOrdering() == Ordering.DEFAULT) {
                visitor.addIdentifier(ASC);
                visitor.addIdentifier(DESC);
            }
        }

        @Override
        public void addIdentifier(AbstractOrderByClause expression, String identifier) {
            visitor.proposals.addIdentifier(identifier);
        }

        @Override
        public void addTheBeginningOfChild(AbstractOrderByClause expression,
                                           CollectionExpression collectionExpression,
                                           int index,
                                           boolean hasComma) {

            if ((index == 0) || hasComma) {
                visitor.addIdentificationVariables();
                visitor.addResultVariables();
            }
        }

        @Override
        public CollectionExpression buildCollectionExpression(AbstractOrderByClause expression) {
            CollectionExpression collectionExpression = visitor.getCollectionExpression(expression.getOrderByItems());
            if (collectionExpression == null) {
                collectionExpression = expression.buildCollectionExpression();
            }
            return collectionExpression;
        }

        @Override
        public boolean canContinue(AbstractOrderByClause expression,
                                   CollectionExpression collectionExpression,
                                   int index) {

            return false;
        }

        @Override
        public boolean hasDelimiterAfterIdentifier(AbstractOrderByClause expression) {
            return expression.hasSpaceAfterIdentifier();
        }

        @Override
        public int maxCollectionSize(AbstractOrderByClause expression) {
            return Integer.MAX_VALUE;
        }

        @Override
        public int preExpressionLength(AbstractOrderByClause expression) {
            return 0;
        }

        @Override
        public JPQLQueryBNF queryBNF(AbstractOrderByClause expression, int index) {
            return visitor.getQueryBNF(OrderByItemBNF.ID);
        }
    }

    // Made static for performance reasons.
    protected static class OrderByClauseStatementHelper
            extends AbstractVisitorHelper implements StatementHelper<SelectStatement> {

        protected OrderByClauseStatementHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public void addClauseProposals() {
            visitor.addCompositeIdentifier(ORDER_BY, -1);
        }

        @Override
        public void addInternalClauseProposals(SelectStatement expression) {
            // Does not have internal clauses
        }

        @Override
        public Expression getClause(SelectStatement expression) {
            return expression.getOrderByClause();
        }

        @Override
        public StatementHelper<SelectStatement> getNextHelper() {
            return null;
        }

        @Override
        public boolean hasClause(SelectStatement expression) {
            return expression.hasOrderByClause();
        }

        @Override
        public boolean hasSpaceAfterClause(SelectStatement expression) {
            return false;
        }

        @Override
        public boolean isClauseComplete(SelectStatement expression) {
            return visitor.isComplete(expression.getOrderByClause());
        }

        @Override
        public boolean isRequired() {
            return false;
        }
    }

    // Made static final for performance reasons.
    protected static final class PropertyMappingFilter implements Filter<IMapping> {

        @Override
        public boolean accept(IMapping value) {
            return !value.isTransient() &&
                   !value.isCollection();
        }
    }

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

        /**
         * The {@link RangeVariableDeclaration} if it was visited otherwise <code>null</code>.
         */
        protected RangeVariableDeclaration expression;

        /**
         * Disposes of the internal data.
         */
        public void dispose() {
            expression = null;
        }

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

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

        /**
         * The {@link ResultVariable} if it was visited otherwise <code>null</code>.
         */
        protected ResultVariable expression;

        /**
         * Disposes of the internal data.
         */
        public void dispose() {
            expression = null;
        }

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

    // Made static final for performance reasons.
    protected static final class SelectClauseCollectionHelper extends AbstractSelectClauseCollectionHelper<SelectClause> {

        protected SelectClauseCollectionHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public void addAtTheEndOfChild(SelectClause expression,
                                       CollectionExpression collectionExpression,
                                       int index,
                                       boolean hasComma,
                                       boolean virtualSpace) {

            super.addAtTheEndOfChild(expression, collectionExpression, index, hasComma, virtualSpace);

            Expression child = collectionExpression.getChild(index);

            // "SELECT e |" <- Valid to add AS
            // "SELECT AVG(e |" <- Invalid to add AS
            if (virtualSpace && visitor.isComplete(child)) {
                visitor.addIdentifier(AS);
            }
        }

        @Override
        public void addTheBeginningOfChild(SelectClause expression,
                                           CollectionExpression collectionExpression,
                                           int index,
                                           boolean hasComma) {

            super.addTheBeginningOfChild(expression, collectionExpression, index, hasComma);

            if (index == 0) {
                visitor.addIdentifier(DISTINCT);
            }
        }

        @Override
        public int preExpressionLength(SelectClause expression) {

            int length = 0;

            if (expression.hasDistinct()) {
                length = 8 /* DISTINCT */;

                if (expression.hasSpaceAfterDistinct()) {
                    length++;
                }
            }

            return length;
        }
    }

    // Made static final for performance reasons.
    protected static final class SelectClauseStatementHelper extends AbstractSelectClauseStatementHelper {

        protected SelectClauseStatementHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public FromClauseStatementHelper getNextHelper() {
            return visitor.getFromClauseStatementHelper();
        }
    }

    // Made static for performance reasons.
    protected static class SimpleFromClauseStatementHelper extends AbstractFromClauseStatementHelper<SimpleSelectStatement> {

        protected SimpleFromClauseStatementHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public SimpleWhereClauseSelectStatementHelper getNextHelper() {
            return visitor.getSimpleWhereClauseSelectStatementHelper();
        }
    }

    // Made static final for performance reasons.
    protected static final class SimpleGroupByClauseStatementHelper extends AbstractGroupByClauseStatementHelper<SimpleSelectStatement> {

        protected SimpleGroupByClauseStatementHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public SimpleHavingClauseStatementHelper getNextHelper() {
            return visitor.getSimpleHavingClauseStatementHelper();
        }
    }

    // Made static final for performance reasons.
    protected static final class SimpleHavingClauseStatementHelper extends AbstractHavingClauseStatementHelper<SimpleSelectStatement> {

        protected SimpleHavingClauseStatementHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public StatementHelper<SimpleSelectStatement> getNextHelper() {
            return null;
        }

        @Override
        public boolean hasSpaceAfterClause(SimpleSelectStatement expression) {
            return false;
        }
    }

    // Made static final for performance reasons.
    protected static final class SimpleSelectClauseCollectionHelper extends AbstractSelectClauseCollectionHelper<SimpleSelectClause> {

        protected SimpleSelectClauseCollectionHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

    }

    // Made static final for performance reasons.
    protected static final class SimpleSelectClauseStatementHelper extends AbstractSelectClauseStatementHelper {

        protected SimpleSelectClauseStatementHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public StatementHelper<SimpleSelectStatement> getNextHelper() {
            return visitor.getSimpleFromClauseStatementHelper();
        }
    }

    // Made static final for performance reasons.
    protected static final class SimpleWhereClauseSelectStatementHelper extends AbstractWhereClauseSelectStatementHelper<SimpleSelectStatement> {

        protected SimpleWhereClauseSelectStatementHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public StatementHelper<SimpleSelectStatement> getNextHelper() {
            return visitor.getSimpleGroupByClauseStatementHelper();
        }
    }

    // Made static for performance reasons.
    /**
     * This helper helps to add JPQL identifiers for the clauses that make up a query statement and
     * also chains the clauses within the query.
     */
    protected static interface StatementHelper<T extends Expression> {

        /**
         * Adds the JPQL identifier of the clause being scanned by this helper.
         * <p>
         * Note: The identifier should not be added directly to the list, it needs to be filtered out
         * based on the location of the cursor, it can be within a word.
         */
        void addClauseProposals();

        /**
         * Adds the JPQL identifier of the internal clause being scanned by this helper. For instance,
         * the <code><b>FROM</b></code> clause could add its own sub-clauses.
         * <p>
         * Note: The identifier should not be added directly to the list, it needs to be filtered out
         * based on the location of the cursor, it can be within a word.
         *
         * @param expression The {@link AbstractSelectStatement} being visited
         */
        void addInternalClauseProposals(T expression);

        /**
         * Returns the clause being scanned by this helper. It is safe to type cast the clause because
         * {@link #hasClause(Expression)} is called before this one.
         *
         * @param expression The {@link AbstractSelectStatement} being visited
         * @return The clause being scanned
         */
        Expression getClause(T expression);

        /**
         * Returns the {@link StatementHelper} that will scan the following clause, which is
         * based on the grammar and not on the actual existence of the clause in the parsed tree.
         *
         * @return The {@link StatementHelper} for the next clause
         */
        StatementHelper<? extends T> getNextHelper();

        /**
         * Determines whether the clause exists in the parsed tree.
         *
         * @param expression The {@link AbstractSelectStatement} being visited
         * @return <code>true</code> if the clause has been parsed; <code>false</code> otherwise
         */
        boolean hasClause(T expression);

        /**
         * Determines whether there is a space (owned by the <b>SELECT</b> statement) after the clause
         * being scanned by this helper.
         *
         * @param expression The {@link AbstractSelectStatement} being visited
         * @return <code>true</code> if a space follows the clause; <code>false</code> otherwise
         */
        boolean hasSpaceAfterClause(T expression);

        /**
         * Determines whether the clause being scanned is complete or not.
         *
         * @param expression The {@link AbstractSelectStatement} being visited
         * @return <code>true</code> if the clause is complete; <code>false</code> otherwise
         */
        boolean isClauseComplete(T expression);

        /**
         * Determines whether the clause is required in order to make the JPQL query grammatically valid.
         *
         * @return <code>true</code> if the clause has to be defined; <code>false</code> if the clause
         * is optional
         */
        boolean isRequired();
    }

    // Made static final for performance reasons.
    protected static final class SubqueryAppendableExpressionVisitor extends AbstractAppendableExpressionVisitor {

        /**
         * For a subquery <code><b>SELECT</b></code> clause identifier to be appendable, it has to be
         * encapsulated by a {@link SubExpression}.
         */
        protected boolean subExpression;

        @Override
        public void visit(IdentificationVariable expression) {
            this.appendable = subExpression;
        }

        @Override
        public void visit(NullExpression expression) {
            this.appendable = subExpression;
        }

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

    // Made static final for performance reasons.
    /**
     * This visitor determines if an {@link Expression} is in a subquery.
     */
    protected static final class SubqueryVisitor extends AbstractTraverseParentVisitor {

        /**
         * The subquery {@link Expression} if it's the first clause visitor. Otherwise it will be
         * <code>null</code> if the {@link Expression} is in the top-level query.
         */
        protected SimpleSelectStatement expression;

        /**
         * Disposes of the internal data.
         */
        public void dispose() {
            expression = null;
        }

        /**
         * Determines whether the visited {@link Expression} is in a subquery or in the top-level query.
         *
         * @return <code>true</code> if the owning query is a subquery; <code>false</code> if it's the
         * top-level query
         */
        public boolean isInSubquery() {
            return expression != null;
        }

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

    // Made static final for performance reasons.
    protected static final class TripleEncapsulatedCollectionHelper
            extends AbstractVisitorHelper implements CollectionExpressionHelper<AbstractTripleEncapsulatedExpression> {

        protected TripleEncapsulatedCollectionHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public void addAtTheEndOfChild(AbstractTripleEncapsulatedExpression expression,
                                       CollectionExpression collectionExpression,
                                       int index,
                                       boolean hasComma,
                                       boolean virtualSpace) {

            // The only thing that is appendable is an arithmetic operator
            // Example: "SELECT e.name|"
            // Example: "SELECT e|"
            if (queryBNF(expression, index).handleAggregate()) {

                Expression child = collectionExpression.getChild(index);

                if ((index == 0) && !virtualSpace) {

                    if (visitor.areArithmeticSymbolsAppendable(child)) {
                        visitor.addArithmeticIdentifiers();
                    }
                }
                else {

                    if (visitor.areArithmeticSymbolsAppendable(child)) {
                        visitor.addArithmeticIdentifiers();
                    }

                    if (visitor.areComparisonSymbolsAppendable(child)) {
                        visitor.addComparisonIdentifiers(child);
                    }
                }
            }
        }

        @Override
        public void addIdentifier(AbstractTripleEncapsulatedExpression expression, String identifier) {
            visitor.proposals.addIdentifier(identifier);
            visitor.addFunctionIdentifiers(expression);
        }

        @Override
        public void addTheBeginningOfChild(AbstractTripleEncapsulatedExpression expression,
                                           CollectionExpression collectionExpression,
                                           int index,
                                           boolean hasComma) {

            visitor.addIdentificationVariables();
            visitor.addFunctionIdentifiers(queryBNF(expression, index));
        }

        @Override
        public CollectionExpression buildCollectionExpression(AbstractTripleEncapsulatedExpression expression) {
            return expression.buildCollectionExpression();
        }

        @Override
        public boolean canContinue(AbstractTripleEncapsulatedExpression expression,
                                   CollectionExpression collectionExpression,
                                   int index) {

            return false;
        }

        @Override
        public boolean hasDelimiterAfterIdentifier(AbstractTripleEncapsulatedExpression expression) {
            return expression.hasSpaceAfterIdentifier() ||
                   expression.hasLeftParenthesis();
        }

        @Override
        public int maxCollectionSize(AbstractTripleEncapsulatedExpression expression) {
            // Both LOCATE and SUBSTRING can allow up to 3 encapsulated expressions
            return 3;
        }

        @Override
        public int preExpressionLength(AbstractTripleEncapsulatedExpression expression) {
            return 0;
        }

        @Override
        public JPQLQueryBNF queryBNF(AbstractTripleEncapsulatedExpression expression, int index) {
            return visitor.getQueryBNF(expression.getParameterQueryBNFId(index));
        }
    }

    // Made static final for performance reasons.
    protected static final class UpdateClauseStatementHelper
            extends AbstractVisitorHelper implements StatementHelper<UpdateStatement> {

        protected UpdateClauseStatementHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public void addClauseProposals() {
            visitor.addIdentifier(UPDATE);
        }

        @Override
        public void addInternalClauseProposals(UpdateStatement expression) {
            // Does not have internal clauses
        }

        @Override
        public Expression getClause(UpdateStatement expression) {
            return expression.getUpdateClause();
        }

        @Override
        public StatementHelper<UpdateStatement> getNextHelper() {
            return visitor.getWhereClauseUpdateStatementHelper();
        }

        @Override
        public boolean hasClause(UpdateStatement expression) {
            return true;
        }

        @Override
        public boolean hasSpaceAfterClause(UpdateStatement expression) {
            return expression.hasSpaceAfterUpdateClause();
        }

        @Override
        public boolean isClauseComplete(UpdateStatement expression) {
            return visitor.isComplete(expression.getUpdateClause());
        }

        @Override
        public boolean isRequired() {
            return true;
        }
    }

    // Made static final for performance reasons.
    protected static final class UpdateItemCollectionHelper
            extends AbstractVisitorHelper implements CollectionExpressionHelper<UpdateClause> {

        protected UpdateItemCollectionHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public void addAtTheEndOfChild(UpdateClause expression,
                                       CollectionExpression collectionExpression,
                                       int index,
                                       boolean hasComma,
                                       boolean virtualSpace) {

            visitor.addAggregateIdentifiers(NewValueBNF.ID);
        }

        @Override
        public void addIdentifier(UpdateClause expression, String identifier) {
            visitor.proposals.addIdentifier(identifier);
        }

        @Override
        public void addTheBeginningOfChild(UpdateClause expression,
                                           CollectionExpression collectionExpression,
                                           int index,
                                           boolean hasComma) {

            visitor.addIdentificationVariables();
        }

        @Override
        public CollectionExpression buildCollectionExpression(UpdateClause expression) {
            CollectionExpression collectionExpression = visitor.getCollectionExpression(expression.getUpdateItems());
            if (collectionExpression == null) {
                collectionExpression = expression.buildCollectionExpression();
            }
            return collectionExpression;
        }

        @Override
        public boolean canContinue(UpdateClause expression,
                                   CollectionExpression collectionExpression,
                                   int index) {

            return false;
        }

        @Override
        public boolean hasDelimiterAfterIdentifier(UpdateClause expression) {
            return expression.hasSpaceAfterUpdate();
        }

        @Override
        public int maxCollectionSize(UpdateClause expression) {
            return Integer.MAX_VALUE;
        }

        @Override
        public int preExpressionLength(UpdateClause expression) {
            // There is a SPACE_LENGTH less, it's added automatically
            return UPDATE.length() +
                   SPACE_LENGTH    +
                   expression.getRangeVariableDeclaration().getLength() +
                   SPACE_LENGTH    +
                   SET.length();
        }

        @Override
        public JPQLQueryBNF queryBNF(UpdateClause expression, int index) {
            return visitor.getQueryBNF(NewValueBNF.ID);
        }
    }

    // Made static final for performance reasons.
    /**
     * This visitor is meant to adjust the corrections stack when traversing an {@link Expression} in
     * order to increase the list of valid proposals.
     * <p>
     * For instance, if the query is "<code>SELECT e FROM Employee e WHERE IN</code>" and the cursor
     * is at the end of the query, then <code>IN</code> would be parsed with {@link InExpression}.
     * However, due to how {@link AbstractContentAssistVisitor} works, the identifier <code>INDEX</code>
     * is not added as a valid proposal. This visitor adds that functionality.
     */
    protected static final class VisitParentVisitor extends AnonymousExpressionVisitor {

        /**
         * Enclosing visitor instance.
         */
        protected final AbstractContentAssistVisitor visitor;

        protected VisitParentVisitor(AbstractContentAssistVisitor visitor) {
            this.visitor = visitor;
        }

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

        @Override
        public void visit(InExpression expression) {

            int position = visitor.queryPosition.getPosition(expression) - visitor.corrections.peek();
            int length = 0;

            if (expression.hasExpression()) {
                length += expression.getExpression().getLength() + SPACE_LENGTH;
            }

            // Within "IN"
            if (visitor.isPositionWithin(position, length, expression.getIdentifier())) {

                boolean hasOnlyIdentifier = !expression.hasExpression() &&
                                            !expression.hasInItems();

                if (hasOnlyIdentifier) {
                    visitor.corrections.add(visitor.queryPosition.getPosition(expression));
                }

                super.visit(expression);

                if (hasOnlyIdentifier) {
                    visitor.corrections.pop();
                }
            }
            else {
                super.visit(expression);
            }
        }
    }

    // Made static final for performance reasons.
    /**
     * This helpers handles adding proposals for {@link WhenClause}.
     */
    protected static final class WhenClauseConditionalClauseCollectionHelper extends AbstractConditionalClauseCollectionHelper<WhenClause> {

        protected WhenClauseConditionalClauseCollectionHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public CollectionExpression buildCollectionExpression(WhenClause expression) {
            CollectionExpression collectionExpression = visitor.getCollectionExpression(expression.getWhenExpression());
            if (collectionExpression == null) {
                collectionExpression = expression.buildWhenCollectionExpression();
            }
            return collectionExpression;
        }

        @Override
        public boolean hasDelimiterAfterIdentifier(WhenClause expression) {
            return expression.hasSpaceAfterWhen();
        }
    }

    // Made static final for performance reasons.
    protected static final class WhereClauseDeleteStatementHelper
            extends AbstractVisitorHelper implements StatementHelper<DeleteStatement> {

        protected WhereClauseDeleteStatementHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public void addClauseProposals() {
            visitor.addIdentifier(WHERE);
        }

        @Override
        public void addInternalClauseProposals(DeleteStatement expression) {
            // Does not have internal clauses
        }

        @Override
        public Expression getClause(DeleteStatement expression) {
            return expression.getWhereClause();
        }

        @Override
        public StatementHelper<? extends DeleteStatement> getNextHelper() {
            return null;
        }

        @Override
        public boolean hasClause(DeleteStatement expression) {
            return expression.hasWhereClause();
        }

        @Override
        public boolean hasSpaceAfterClause(DeleteStatement expression) {
            return false;
        }

        @Override
        public boolean isClauseComplete(DeleteStatement expression) {
            return visitor.isComplete(expression.getWhereClause());
        }

        @Override
        public boolean isRequired() {
            return false;
        }
    }

    // Made static final for performance reasons.
    protected static final class WhereClauseSelectStatementHelper extends AbstractWhereClauseSelectStatementHelper<SelectStatement> {

        protected WhereClauseSelectStatementHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public StatementHelper<SelectStatement> getNextHelper() {
            return visitor.getGroupByClauseStatementHelper();
        }
    }

    // Made static final for performance reasons.
    protected static final class WhereClauseUpdateStatementHelper
            extends AbstractVisitorHelper implements StatementHelper<UpdateStatement> {

        protected WhereClauseUpdateStatementHelper(AbstractContentAssistVisitor visitor) {
            super(visitor);
        }

        @Override
        public void addClauseProposals() {
            visitor.addIdentifier(WHERE);
        }

        @Override
        public void addInternalClauseProposals(UpdateStatement expression) {
            // Does not have internal clauses
        }

        @Override
        public Expression getClause(UpdateStatement expression) {
            return expression.getWhereClause();
        }

        @Override
        public StatementHelper<? extends UpdateStatement> getNextHelper() {
            return null;
        }

        @Override
        public boolean hasClause(UpdateStatement expression) {
            return expression.hasWhereClause();
        }

        @Override
        public boolean hasSpaceAfterClause(UpdateStatement expression) {
            return false;
        }

        @Override
        public boolean isClauseComplete(UpdateStatement expression) {
            return visitor.isComplete(expression.getWhereClause());
        }

        @Override
        public boolean isRequired() {
            return false;
        }
    }

    // Made static final for performance reasons.
    protected static final class WithinInvalidExpressionVisitor extends AbstractTraverseParentVisitor {

        /**
         * Determines whether the visited {@link Expression} is an descendant of either a bad or
         * invalid expression.
         */
        protected boolean withinInvalidExpression;

        /**
         * Disposes of the internal data.
         */
        public void dispose() {
            withinInvalidExpression = false;
        }

        /**
         * Determines whether the visited {@link Expression} is part of an invalid fragment
         *
         * @return <code>true</code> if the visited {@link Expression} is within an invalid fragment;
         * <code>false</code> if it is not
         */
        public boolean isWithinInvalidExpression() {
            return withinInvalidExpression;
        }

        @Override
        public void visit(BadExpression expression) {
            withinInvalidExpression = true;
        }

        @Override
        public void visit(UnknownExpression expression) {
            withinInvalidExpression = true;
        }
    }
}
