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