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

// Contributors:
//     Oracle - initial API and implementation
//
package org.eclipse.persistence.jpa.jpql.parser;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.persistence.jpa.jpql.ExpressionTools;
import org.eclipse.persistence.jpa.jpql.JPAVersion;
import org.eclipse.persistence.jpa.jpql.WordParser;
import org.eclipse.persistence.jpa.jpql.WordParser.WordType;
import org.eclipse.persistence.jpa.jpql.utility.iterable.ListIterable;
import org.eclipse.persistence.jpa.jpql.utility.iterable.SnapshotCloneListIterable;

/**
 * This is the abstract definition of all the parts used to create the tree hierarchy representing
 * the parsed JPQL query.
 *
 * @see ExpressionFactory
 * @see JPQLGrammar
 *
 * @version 2.6
 * @since 2.3
 * @author Pascal Filion
 */
@SuppressWarnings("nls")
public abstract class AbstractExpression implements Expression {

    /**
     * The string representation of this {@link AbstractExpression} (which includes its children).
     * The string includes characters that are considered virtual, i.e. that was parsed when the
     * query is incomplete and is needed for functionality like content assist.
     *
     * @see #toActualText()
     */
    private String actualText;

    /**
     * The children of this {@link AbstractExpression}.
     *
     * @see #children()
     */
    private List<Expression> children;

    /**
     * The position of this {@link AbstractExpression} in relation to its parent hierarchy by
     * calculating the length of the string representation of what comes before.
     */
    private int offset;

    /**
     * The string representation of this {@link AbstractExpression}.
     *
     * @see #orderedChildren()
     */
    private List<Expression> orderedChildren;

    /**
     * The parent of this {@link AbstractExpression} or <code>null</code> if this object is {@link
     * JPQLExpression} - the root of the parsed tree hierarchy.
     */
    private AbstractExpression parent;

    /**
     * The string representation of this {@link AbstractExpression} (which includes its children).
     * The string does not include characters that are considered virtual, i.e. that was parsed when
     * the query is incomplete.
     *
     * @see #toParsedText()
     */
    private String parsedText;

    /**
     * This attribute can be used to store the {@link AbstractExpression}'s JPQL identifier or a literal.
     */
    private String text;

    /**
     * The constant for ','.
     */
    public static final char COMMA = ',';

    /**
     * The constant for '.'.
     */
    public static final char DOT = '.';

    /**
     * The constant for '"'.
     */
    public static final char DOUBLE_QUOTE = '\"';

    /**
     * The constant for '{'.
     */
    public static final char LEFT_CURLY_BRACKET = '{';

    /**
     * The constant for '('.
     */
    public static final char LEFT_PARENTHESIS = '(';

    /**
     * The constant for a character that is not defined.
     */
    public static final char NOT_DEFINED = '\0';

    /**
     * The constant for '}'.
     */
    public static final char RIGHT_CURLY_BRACKET = '}';

    /**
     * The constant for ')'.
     */
    public static final char RIGHT_PARENTHESIS = ')';

    /**
     * The constant for '''.
     */
    public static final char SINGLE_QUOTE = '\'';

    /**
     * The constant for ' '.
     */
    public static final char SPACE = ' ';

    /**
     * The constant for '_'.
     */
    public static final char UNDERSCORE = '_';

    /**
     * Creates a new <code>AbstractExpression</code>.
     *
     * @param parent The parent of this expression
     */
    protected AbstractExpression(AbstractExpression parent) {
        this(parent, ExpressionTools.EMPTY_STRING);
    }

    /**
     * Creates a new <code>AbstractExpression</code>.
     *
     * @param parent The parent of this expression
     * @param text The text to be stored in this expression, <code>null</code> cannot be passed
     */
    protected AbstractExpression(AbstractExpression parent, String text) {
        super();
        this.offset = -1;
        this.text   = text;
        this.parent = parent;
    }

    /**
     * The given {@link ExpressionVisitor} needs to visit this class but it is defined by a third-
     * party provider. This method will programmatically invoke the <b>visit</b> method defined on
     * the visitor. The method signature should be:
     *
     * <div><code>{public|protected|private} void visit(ThirdPartyExpression expression)</code></div>
     * <p>
     * or
     *
     * <div><code>{public|protected|private} void visit(Expression expression)</code></div>
     * <p>
     * <b>Note:</b> The package protected visibility (default) should be used with care, if the code
     * is running inside OSGi, then the method will not be accessible, even through reflection.
     *
     * @param visitor The {@link ExpressionVisitor} to visit this {@link Expression} programmatically
     * @return <code>true</code> if the call was successfully executed; <code>false</code> otherwise
     * @since 2.4
     */
    protected boolean acceptUnknownVisitor(ExpressionVisitor visitor) {
        try {
            try {
                acceptUnknownVisitor(visitor, visitor.getClass(), getClass());
            }
            catch (NoSuchMethodException e) {
                // Try with Expression as the parameter type
                acceptUnknownVisitor(visitor, visitor.getClass(), Expression.class);
            }
            return true;
        }
        catch (NoSuchMethodException e) {
            // Ignore, just do nothing
            return false;
        }
        catch (IllegalAccessException e) {
            // Ignore, just do nothing
            return false;
        }
        catch (InvocationTargetException e) {
            Throwable cause = e.getCause();
            RuntimeException actual;
            if (cause instanceof RuntimeException) {
                actual = (RuntimeException) cause;
            }
            else {
                actual = new RuntimeException(cause);
            }
            throw actual;
        }
    }

    /**
     * The given {@link ExpressionVisitor} needs to visit this class but it is defined by a third-
     * party provider. This method will programmatically invoke the <b>visit</b> method defined on
     * the visitor. The method signature should be:
     *
     * <div><code>{public|protected|private} void visit(ThirdPartyExpression expression)</code></div>
     * <p>
     * or
     *
     * <div><code>{public|protected|private} void visit(Expression expression)</code></div>
     * <p>
     *
     * @param visitor The {@link ExpressionVisitor} to visit this {@link Expression} programmatically
     * @param type The type found in the hierarchy of the given {@link ExpressionVisitor} that will
     * be used to retrieve the visit method
     * @param parameterType The parameter type of the visit method
     * @see #acceptUnknownVisitor(ExpressionVisitor)
     * @since 2.4
     */
    protected void acceptUnknownVisitor(ExpressionVisitor visitor,
                                        Class<?> type,
                                        Class<?> parameterType) throws NoSuchMethodException,
                                                                       IllegalAccessException,
                                                                       InvocationTargetException{

        try {
            Method visitMethod = type.getDeclaredMethod("visit", parameterType);
            visitMethod.setAccessible(true);
            visitMethod.invoke(visitor, this);
        }
        catch (NoSuchMethodException e) {
            type = type.getSuperclass();
            if (type == Object.class) {
                throw e;
            }
            else {
                acceptUnknownVisitor(visitor, type, parameterType);
            }
        }
    }

    /**
     * Adds the children of this {@link AbstractExpression} to the given collection.
     *
     * @param children The collection used to store the children
     */
    protected void addChildrenTo(Collection<Expression> children) {
    }

    /**
     * Adds the children of this {@link AbstractExpression} to the given list.
     *
     * @param children The list used to store the string representation of this {@link AbstractExpression}
     */
    protected void addOrderedChildrenTo(List<Expression> children) {
    }

    /**
     * No factories were found to create an {@link Expression} with the content of {@link WordParser},
     * this method will retrieve the fallback {@link ExpressionFactory} defined in the given {@link
     * JPQLQueryBNF BNF}.
     *
     * @param wordParser The text to parse based on the current position of the cursor
     * @param word The word that was retrieved from the given text, which is the first word in the text
     * @param queryBNF The {@link JPQLQueryBNF} used to determine how to parse from the current
     * position of the cursor within the JPQL query
     * @param expression The {@link Expression} that has just been parsed or <code>null</code>
     * @param tolerant Determines whether the parsing system should be tolerant, meaning if it should
     * try to parse invalid or incomplete queries
     * @return The {@link Expression} representing the given sub-query
     */
    protected final AbstractExpression buildExpressionFromFallingBack(WordParser wordParser,
                                                                      String word,
                                                                      JPQLQueryBNF queryBNF,
                                                                      AbstractExpression expression,
                                                                      boolean tolerant) {

        ExpressionFactory factory = findFallBackExpressionFactory(queryBNF);

        if (factory == null) {
            return null;
        }

        // When parsing an invalid or incomplete query, it is possible two literals would be parsed
        // but in some cases, a CollectionExpression should not be created and the parsing should
        // actually stop here. Example: BETWEEN 10 20, when parsing 20, it should not be parsed as
        // part of the lower bound expression
        if (tolerant &&
            (factory.getId() == LiteralExpressionFactory.ID) &&
            shouldSkipLiteral(expression)) {

            return null;
        }

        return factory.buildExpression(this, wordParser, word, queryBNF, expression, tolerant);
    }

    /**
     * Creates a new <code>null</code>-{@link Expression} parented with this one.
     *
     * @return A new <code>null</code> version of an {@link Expression}
     */
    protected final AbstractExpression buildNullExpression() {
        return new NullExpression(this);
    }

    /**
     * Creates a new {@link Expression} wrapping the given character value.
     *
     * @param value The character to wrap as a {@link Expression}
     * @return The {@link Expression} representation of the given identifier where the owning
     * {@link Expression} is this one
     */
    protected final Expression buildStringExpression(char value) {
        return buildStringExpression(String.valueOf(value));
    }

    /**
     * Creates a new {@link Expression} wrapping the given string value.
     *
     * @param value The string to wrap as a <code>Expression</code>
     * @return The {@link Expression} representation of the given identifier where the owning
     * {@link Expression} is this one
     */
    protected final Expression buildStringExpression(String value) {
        return new DefaultStringExpression(this, value);
    }

    /**
     * Creates an {@link Expression} that contains a malformed expression.
     *
     * @param text The text causing the expression to be malformed
     * @return A new {@link Expression} where {@link #toActualText()} returns the given text
     */
    protected final AbstractExpression buildUnknownExpression(String text) {
        return new UnknownExpression(this, text);
    }

    /**
     * Calculates the position of the given {@link Expression} by calculating the length of what is before.
     *
     * @param expression The {@link Expression} for which its position within the parsed tree needs
     * to be determined
     * @param length The current cursor position within the JPQL query while digging into the tree
     * until the search reaches the expression
     * @return The length of the string representation for what is coming before the given {@link Expression}
     * @since 2.4
     */
    protected final int calculatePosition(Expression expression, int length) {

        Expression parent = expression.getParent();

        // Reach the root
        if (parent == null) {
            return length;
        }

        // Traverse the child expression until the expression
        for (Expression childExpression : parent.orderedChildren()) {

            // Continue to calculate the position by going up the hierarchy
            if (childExpression == expression) {
                return calculatePosition(parent, length);
            }

            length += childExpression.getLength();
        }

        // It should never reach this
        throw new RuntimeException("The position of the Expression could not be calculated: " + expression);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final ListIterable<Expression> children() {
        if (children == null) {
            children = new LinkedList<Expression>();
            addChildrenTo(children);
        }
        return new SnapshotCloneListIterable<Expression>(children);
    }

    /**
     * Retrieve the {@link ExpressionFactory} from the given {@link JPQLQueryBNF} by following the
     * path of fallback {@link JPQLQueryBNF JPQLQueryBNFs} and then returns the {@link ExpressionFactory}
     * from the leaf {@link JPQLQueryBNF}.
     *
     * @param queryBNF The {@link JPQLQueryBNF} for which its associated fallback {@link ExpressionFactory}
     * will be searched
     * @return Either the fallback {@link ExpressionFactory} linked to the given {@link JPQLQueryBNF}
     * or <code>null</code> if none was declared
     */
    protected final ExpressionFactory findFallBackExpressionFactory(JPQLQueryBNF queryBNF) {

        String fallBackBNFId = queryBNF.getFallbackBNFId();

        // No fall back BNF is defined, then nothing can be done
        if (fallBackBNFId == null) {
            return null;
        }

        JPQLQueryBNF fallBackQueryBNF = getQueryBNF(fallBackBNFId);

        // Traverse the fall back BNF because it has its own fall back BNF
        if (fallBackQueryBNF != queryBNF &&
            fallBackQueryBNF.getFallbackBNFId() != null) {

            return findFallBackExpressionFactory(fallBackQueryBNF);
        }

        // Retrieve the factory associated with the fall back BNF
        return getExpressionRegistry().getExpressionFactory(fallBackQueryBNF.getFallbackExpressionFactoryId());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public JPQLQueryBNF findQueryBNF(Expression expression) {
        return getQueryBNF();
    }

    /**
     * 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
     * @see ExpressionRegistry#getExpressionFactory(String)
     */
    protected final ExpressionFactory getExpressionFactory(String expressionFactoryId) {
        return getExpressionRegistry().getExpressionFactory(expressionFactoryId);
    }

    /**
     * Returns the registry containing the {@link JPQLQueryBNF JPQLQueryBNFs} and the {@link
     * org.eclipse.persistence.jpa.jpql.parser.ExpressionFactory ExpressionFactories} that are used
     * to properly parse a JPQL query.
     *
     * @return The registry containing the information related to the JPQL grammar
     */
    protected final ExpressionRegistry getExpressionRegistry() {
        return getGrammar().getExpressionRegistry();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public JPQLGrammar getGrammar() {
        return getRoot().getGrammar();
    }

    /**
     * Retrieves the JPA version in which the identifier was first introduced.
     *
     * @return The version in which the identifier was introduced
     */
    public JPAVersion getIdentifierVersion(String identifier) {
        return getRoot().getIdentifierVersion(identifier);
    }

    /**
     * Returns the version of the Java Persistence to support.
     *
     * @return The JPA version supported by the grammar
     * @see JPQLGrammar
     */
    protected JPAVersion getJPAVersion() {
        return getRoot().getJPAVersion();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final int getLength() {
        return toActualText().length();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final int getOffset() {
        if (offset == -1) {
            offset = calculatePosition(this, 0);
        }
        return offset;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final AbstractExpression getParent() {
        return parent;
    }

    /**
     * Retrieves the BNF object 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
     */
    public JPQLQueryBNF getQueryBNF(String queryBNFID) {
        return getExpressionRegistry().getQueryBNF(queryBNFID);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final JPQLExpression getRoot() {
        return (parent == null) ? (JPQLExpression) this : parent.getRoot();
    }

    /**
     * Returns the encapsulated text of this {@link AbstractExpression}, which can be used in various
     * ways, it can be a keyword, a literal, etc.
     *
     * @return Either the JPQL identifier for this {@link AbstractExpression}, the literal it
     * encapsulates or an empty string
     */
    protected String getText() {
        return text;
    }

    /**
     * Determines whether the given {@link JPQLQueryBNF} handles aggregate expressions.
     *
     * @param queryBNF The {@link JPQLQueryBNF} used to determine if the parsing should handle
     * aggregate expressions
     * @return <code>true</code> if the given BNF handles aggregate expressions; <code>false</code>
     * otherwise
     */
    protected boolean handleAggregate(JPQLQueryBNF queryBNF) {
        return queryBNF.handleAggregate();
    }

    /**
     * Determines whether the given {@link JPQLQueryBNF} handles a collection of sub-expressions that
     * are separated by commas.
     *
     * @param queryBNF The {@link JPQLQueryBNF} used to determine if the parsing should handle
     * collection of sub-expressions
     * @return <code>true</code> if the sub-expression to parse might have several sub-expressions
     * separated by commas; <code>false</code> otherwise
     */
    protected boolean handleCollection(JPQLQueryBNF queryBNF) {
        return queryBNF.handleCollection();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isAncestor(Expression expression) {

        if (expression == this) {
            return true;
        }

        if (expression == null) {
            return false;
        }

        return isAncestor(expression.getParent());
    }

    /**
     * Determines if the given word is a JPQL identifier. The check is case insensitive.
     *
     * @param word The word to test if it is a JPQL identifier
     * @return <code>true</code> if the word is an identifier, <code>false</code> otherwise
     * @see ExpressionRegistry#isIdentifier(String)
     */
    protected final boolean isIdentifier(String word) {
        return getExpressionRegistry().isIdentifier(word);
    }

    /**
     * Determines whether this expression is a <code>null</code> {@link Expression} or any other subclass.
     *
     * @return <code>false</code> by default
     */
    protected boolean isNull() {
        return false;
    }

    /**
     * Determines whether the parsing is complete based on what is left in the given text. The text
     * is never empty.
     *
     * @param wordParser The text to parse based on the current position of the cursor
     * @param word The word that was retrieved from the given text, which is the first word in the text
     * @param expression The {@link Expression} that has already been parsed
     * @return <code>true</code> if the text no longer can't be parsed by the current expression;
     * <code>false</code> if more can be parsed
     */
    protected boolean isParsingComplete(WordParser wordParser, String word, Expression expression) {
        // TODO: MAYBE MOVE THIS TO THE JPQL GRAMMAR SO GENERIC JPA DOES
        //       NOT HAVE KNOWLEDGE OF ECLIPSELINK SPECIFIC FUNCTIONS
        return word.equalsIgnoreCase(FROM)                        ||
               word.equalsIgnoreCase(WHERE)                       ||
               word.equalsIgnoreCase(HAVING)                      ||
               wordParser.startsWithIdentifier(GROUP_BY)          ||
               wordParser.startsWithIdentifier(ORDER_BY)          ||
               wordParser.startsWithIdentifier(AS_OF)             ||
               wordParser.startsWithIdentifier(START_WITH)        ||
               wordParser.startsWithIdentifier(CONNECT_BY)        ||
               wordParser.startsWithIdentifier(ORDER_SIBLINGS_BY) ||
               word.equalsIgnoreCase(UNION)                       ||
               word.equalsIgnoreCase(INTERSECT)                   ||
               word.equalsIgnoreCase(EXCEPT);
    }

    /**
     * Determines if the parser is in tolerant mode or is in fast mode. When the tolerant is turned
     * on, it means the parser will attempt to parse incomplete or invalid queries.
     *
     * @return <code>true</code> if the parsing system should parse invalid or incomplete queries;
     * <code>false</code> when the query is well-formed and valid
     */
    protected boolean isTolerant() {
        return getRoot().isTolerant();
    }

    /**
     * Determines whether this expression is an unknown {@link Expression} or any other subclass.
     *
     * @return <code>false</code> by default
     */
    protected boolean isUnknown() {
        return false;
    }

    /**
     * Determines whether this {@link AbstractExpression} is virtual, meaning it's not part of the
     * query but is required for proper navigability.
     *
     * @return <code>true</code> if this {@link AbstractExpression} was virtually created to fully
     * qualify path expression; <code>false</code> if it was parsed
     */
    protected boolean isVirtual() {
        return false;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final ListIterable<Expression> orderedChildren() {
        if (orderedChildren == null) {
            orderedChildren = new LinkedList<Expression>();
            addOrderedChildrenTo(orderedChildren);
        }
        return new SnapshotCloneListIterable<Expression>(orderedChildren);
    }

    /**
     * Parses the query by starting at the current position, which is part of the given {@link WordParser}.
     *
     * @param wordParser The text to parse based on the current position of the cursor
     * @param tolerant Determines whether the parsing system should be tolerant, meaning if it should
     * try to parse invalid or incomplete queries
     */
    protected abstract void parse(WordParser wordParser, boolean tolerant);

    /**
     * Parses the given text by using the specified BNF.
     *
     * @param wordParser The text to parse based on the current position of the cursor
     * @param queryBNFId The unique identifier of the {@link JPQLQueryBNF} that is used to determine
     * how to parse the text at the current cursor position within the JPQL query
     * @param tolerant Determines whether the parsing system should be tolerant, meaning if it should
     * try to parse invalid or incomplete queries
     * @return The {@link Expression} representing the given sub-query
     */
    @SuppressWarnings("null")
    protected AbstractExpression parse(WordParser wordParser, String queryBNFId, boolean tolerant) {

        // Quick check so we don't create some objects for no reasons
        if (tolerant && wordParser.isTail()) {
            return null;
        }

        //
        // NOTE: This method could look better but for performance reason, it is a single method,
        //       which reduces the number of objects created and methods called.
        //

        JPQLQueryBNF queryBNF = getQueryBNF(queryBNFId);

        int count = 0;
        boolean beginning = !tolerant;
        char character = wordParser.character();

        AbstractExpression child;
        AbstractExpression expression = null;

        Info rootInfo = null;
        Info currentInfo = null;

        // Parse the string until the position of the cursor is at
        // the end of the string or until the parsing is complete
        while (!wordParser.isTail()) {

            child = null;

            //
            // Step 1
            //
            // Right away create a SubExpression and parse the encapsulated expression
            if (character == LEFT_PARENTHESIS) {

                // If the JPQLQueryBNF handles parsing the sub-expression, then delegate the parsing
                // to its fallback ExpressionFactory
                if (queryBNF.handleSubExpression()) {
                    expression = buildExpressionFromFallingBack(
                        wordParser,
                        ExpressionTools.EMPTY_STRING,
                        queryBNF,
                        expression,
                        tolerant
                    );
                }
                else {
                    expression = new SubExpression(this, queryBNF);
                    expression.parse(wordParser, tolerant);

                    // Make sure this is not the root and if the parent handles parsing the sub-
                    // expression, then the Expression needs to be returned without further parsing
                    if ((parent != null) && parent.getQueryBNF().handleSubExpression()) {
                        return expression;
                    }
                }

                // Something has been parsed, which means it's not the beginning anymore
                beginning = false;

                // Continue to the next character/word
                count     = wordParser.skipLeadingWhitespace();
                character = wordParser.character();

                // Store the SubExpression
                currentInfo = (rootInfo == null) ? (rootInfo = new Info()) : (currentInfo.next = new Info(currentInfo));
                currentInfo.expression = expression;
                currentInfo.space = count > 0;
            }

            // Retrieve the next word, including any arithmetic symbols
            String word = wordParser.word();

            // A word was parsed, attempt to parse it using first the factory, then the fallback factory
            if (word.length() > 0) {

                // Nothing more to parse
                if (!tolerant && !beginning && isParsingComplete(wordParser, word, expression) ||
                     tolerant &&               isParsingComplete(wordParser, word, expression)) {

                    break;
                }

                //
                // Step 2
                //
                // Parse using the ExpressionFactory that is mapped with a JPQL identifier (word)
                if (shouldParseWithFactoryFirst() &&
                    (wordParser.getWordType() == WordType.WORD)) {

                    ExpressionFactory factory = queryBNF.getExpressionFactory(word);

                    if (factory != null) {
                        child = factory.buildExpression(this, wordParser, word, queryBNF, expression, tolerant);

                        if (child != null) {

                            // The new expression is a child of the previous expression,
                            // remove it from the collection since it's already parented
                            if ((expression != null) && child.isAncestor(expression)) {
                                if (currentInfo == rootInfo) {
                                    rootInfo = null;
                                    currentInfo = null;
                                }
                                else if (currentInfo != null) {
                                    currentInfo = currentInfo.previous;
                                }
                            }

                            // Something has been parsed, which means it's not the beginning anymore
                            beginning = false;

                            // Continue with the next character/word
                            count     = wordParser.skipLeadingWhitespace();
                            character = wordParser.character();

                            // The new expression becomes the previous expression
                            expression = child;
                        }
                    }
                }

                //
                // Step 3
                //
                // No factories could be used, use the fall back ExpressionFactory
                if (child == null) {
                    child = buildExpressionFromFallingBack(wordParser, word, queryBNF, expression, tolerant);

                    if (child != null) {

                        // The new expression is a child of the previous expression,
                        // remove it from the collection since it's already parented
                        if ((expression != null) && child.isAncestor(expression)) {
                            if (currentInfo == rootInfo) {
                                rootInfo = null;
                                currentInfo = null;
                            }
                            else if (currentInfo != null) {
                                currentInfo = currentInfo.previous;
                            }
                        }

                        // Something has been parsed, which means it's not the beginning anymore
                        beginning = false;

                        // Continue with the next character/word
                        count     = wordParser.skipLeadingWhitespace();
                        character = wordParser.character();

                        // The new expression becomes the previous expression
                        expression = child;
                    }
                }

                //
                // Step 4
                //
                // If nothing was parsed, then attempt to parse the fragment by retrieving the factory
                // directory from the JPQL grammar and not from the one registered with the current BNF
                if (tolerant && (child == null)) {

                    ExpressionRegistry expressionRegistry = getExpressionRegistry();

                    if (expressionRegistry.getIdentifierRole(word) != IdentifierRole.AGGREGATE) {

                        ExpressionFactory factory = expressionRegistry.expressionFactoryForIdentifier(word);

                        if (factory != null) {
                            child = factory.buildExpression(this, wordParser, word, queryBNF, expression, tolerant);

                            if (child != null) {
                                child = new BadExpression(this, child);

                                // The new expression is a child of the previous expression,
                                // remove it from the collection since it's already parented
                                if ((expression != null) && child.isAncestor(expression)) {
                                    if (currentInfo == rootInfo) {
                                        rootInfo = null;
                                        currentInfo = null;
                                    }
                                    else if (currentInfo != null) {
                                        currentInfo = currentInfo.previous;
                                    }
                                }

                                // Something has been parsed, which means it's not the beginning anymore
                                beginning = false;

                                // Continue with the next character/word
                                count     = wordParser.skipLeadingWhitespace();
                                character = wordParser.character();

                                // The new expression becomes the previous expression
                                expression = child;
                            }
                        }
                    }
                }
            }

            // Nothing could be parsed, break here so the parent can continue parsing.
            // Example: AVG() and we're parsing what's inside the parenthesis (nothing).
            // But if it's (,), then we have to create a collection of "null" expressions
            // separated by a comma
            if ((child == null) && (character != COMMA)) {
                break;
            }

            // Store the child but skip a very special case, which happens when parsing
            // two subqueries in a collection expression. Example: (SELECT ... ), (SELECT ... )
            if ((expression == null) || (child != null)) {
                currentInfo = (rootInfo == null) ? (rootInfo = new Info()) : (currentInfo.next = new Info(currentInfo));
                currentInfo.expression = child;
                currentInfo.space = count > 1;
            }

            // Nothing else to parse
            if (wordParser.isTail()) {
                break;
            }

            // ','
            if (character == COMMA) {

                // The current expression does not handle collection, then stop the
                // parsing here so the parent can continue to parse
                if (!handleCollection(queryBNF) || tolerant && isParsingComplete(wordParser, word, expression)) {
                    break;
                }

                // Skip the comma
                wordParser.moveForward(1);
                currentInfo.comma = true;

                // Remove leading whitespace
                count = wordParser.skipLeadingWhitespace();
                currentInfo.space = count > 0;

                character = wordParser.character();
                expression = null;

                // Special case: ((), (), ())
                if (character == LEFT_PARENTHESIS) {
                    continue;
                }

                // No more text, the query ends with a comma
                word = wordParser.word();
                boolean stopParsing = tolerant && (word.length() == 0 || isParsingComplete(wordParser, word, null));

                if (wordParser.isTail() || stopParsing) {

                    // Make sure the space is not re-added at the end of the query
                    count = 0;

                    // Add a null Expression since the expression ends with a comma
                    currentInfo = (rootInfo == null) ? (rootInfo = new Info()) : (currentInfo.next = new Info(currentInfo));

                    // Nothing else to parse
                    if (stopParsing) {
                        break;
                    }
                }

                // Nothing more to parse
                if (character == RIGHT_PARENTHESIS) {
                    break;
                }
            }
            else {

                // Continue parsing the collection expression
                if (character != RIGHT_PARENTHESIS &&
                    handleAggregate(queryBNF)) {

                    currentInfo.space = count > 0;
                }
                // Nothing more to parse
                else {
                    break;
                }
            }
        }

        if (count > 0) {
            currentInfo.space = currentInfo.comma;
            if (!currentInfo.comma) {
                wordParser.moveBackward(count);
            }
        }

        // Nothing was parsed
        if (currentInfo == null) {
            return null;
        }

        // Simply return the single expression
        if (currentInfo == rootInfo &&
           !currentInfo.comma &&
           !currentInfo.space) {

            return currentInfo.expression;
        }

        // Return a collection of expressions
        return new CollectionExpression(
            this,
            rootInfo.buildChildren(),
            rootInfo.buildCommas(),
            rootInfo.buildSpaces()
        );
    }

    /**
     * Right away parses the text by retrieving the {@link ExpressionFactory} for the first word that
     * is extracted from {@link WordParser} at the current location.
     *
     * @param wordParser The text to parse based on the current position of the cursor
     * @param queryBNFId The unique identifier of the {@link JPQLQueryBNF} that is used to determine
     * how to parse the text at the current cursor position within the JPQL query
     * @param tolerant Determines whether the parsing system should be tolerant, meaning if it should
     * try to parse invalid or incomplete queries
     * @return The {@link Expression} representing the given sub-query
     */
    protected AbstractExpression parseUsingExpressionFactory(WordParser wordParser,
                                                             String queryBNFId,
                                                             boolean tolerant) {

        String word = wordParser.word();
        JPQLQueryBNF queryBNF = getQueryBNF(queryBNFId);
        ExpressionFactory factory = queryBNF.getExpressionFactory(word);

        if (factory == null) {
            return null;
        }

        return factory.buildExpression(this, wordParser, word, queryBNF, null, tolerant);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void populatePosition(QueryPosition queryPosition, int position) {

        queryPosition.addPosition(this, position);

        // The position is at the beginning of this expression
        if (position == 0) {
            queryPosition.setExpression(this);
        }
        else {
            // Traverse the children in order to find where the cursor is located
            for (Expression expression : orderedChildren()) {

                String expressionText = expression.toParsedText();

                // The position is in the Expression, traverse it
                if (position <= expressionText.length()) {
                    expression.populatePosition(queryPosition, position);
                    return;
                }

                // Continue with the next child by adjusting the position
                position -= expressionText.length();
            }

            throw new IllegalStateException("A problem was encountered while calculating the position.");
        }
    }

    /**
     * Rebuilds the actual parsed text if it has been cached.
     */
    protected final void rebuildActualText() {
        if (actualText != null) {
            toActualText();
        }
    }

    /**
     * Rebuilds the parsed parsed text if it has been cached.
     */
    protected final void rebuildParsedText() {
        if (parsedText != null) {
            toParsedText();
        }
    }

    /**
     * Re-parents this {@link Expression} to be a child of the given {@link Expression}.
     *
     * @param parent The new parent of this object
     */
    protected final void setParent(AbstractExpression parent) {
        this.parent = parent;
    }

    /**
     * Sets the text of this {@link Expression}.
     *
     * @param text The immutable text wrapped by this {@link Expression}, which cannot be <code>null</code>
     */
    protected final void setText(String text) {
        this.text = text;
    }

    /**
     * Determines whether the parsing of the query should be performed using the {@link ExpressionFactory
     * factories} first or it should automatically fallback to the fallback factory.
     *
     * @return <code>true</code> is returned by default so the factories are used before falling back
     */
    protected boolean shouldParseWithFactoryFirst() {
        return true;
    }

    /**
     * When parsing an invalid or incomplete query, it is possible two literals would be parsed but
     * in some cases, a CollectionExpression should not be created and the parsing should actually
     * stop here. Example: BETWEEN 10 20, when parsing 20, it should not be parsed as part of the
     * lower bound expression.
     *
     * @param expression The {@link Expression} that has just been parsed or <code>null</code>
     * @return <code>true</code>
     */
    protected boolean shouldSkipLiteral(AbstractExpression expression) {
        return (expression != null);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toActualText() {
        if (actualText == null) {
            StringBuilder writer = new StringBuilder();
            toParsedText(writer, true);
            actualText = writer.toString();
        }
        return actualText;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toParsedText() {
        if (parsedText == null) {
            StringBuilder writer = new StringBuilder();
            toParsedText(writer, false);
            parsedText = writer.toString();
        }
        return parsedText;
    }

    /**
     * Generates a string representation of this {@link Expression}, including its children,
     * if it has any.
     *
     * @param writer The buffer used to append this {@link Expression}'s string representation
     * @param actual Determines whether the string representation should represent what was parsed,
     * i.e. include any "virtual" whitespace (such as ending whitespace) and the actual case of the
     * JPQL identifiers
     */
    protected abstract void toParsedText(StringBuilder writer, boolean actual);

    /**
     * {@inheritDoc}
     */
    @Override
    public final String toString() {
        // toString() should only be called during debugging, thus the cached parsed text
        // should always be recreated in order to reflect the current state while debugging
        parsedText = null;
        return toParsedText();
    }

    /**
     * Rather than creating three lists when performing a single parsing operation ({@link
     * AbstractExpression#parse(WordParser, String, boolean) parse(WordParser, String, boolean)}),
     * this class will act as a simple chained list and postponing the creation of those three lists
     * only when needed (which is when the parsed expression needs to be a collection of expressions).
     */
    private static class Info {

        /**
         * Flag indicating a comma follows the parsed {@link #expression}.
         */
        boolean comma;

        /**
         * The parsed {@link Expression}, which is the first one that was parsed if {@link #next} is
         * <code>null</code>, meaning this <code>Info</code> object is the root of the chained list.
         */
        AbstractExpression expression;

        /**
         * When more than one expression needs to be parsed, it will be chained.
         */
        Info next;

        /**
         * The parent within the chain of this one.
         */
        Info previous;

        /**
         * Flag indicating a whitespace follows the parsed {@link #expression}.
         */
        boolean space;

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

        /**
         * Creates a new <code>Info</code>.
         *
         * @param previous The parent within the chain of this one
         */
        Info(Info previous) {
            super();
            this.previous = previous;
        }

        private void addChild(ArrayList<AbstractExpression> children) {
            children.add(expression);
            if (next != null) {
                next.addChild(children);
            }
        }

        private void addComma(ArrayList<Boolean> children) {
            children.add(comma);
            if (next != null) {
                next.addComma(children);
            }
        }

        private void addSpace(ArrayList<Boolean> children) {
            children.add(space);
            if (next != null) {
                next.addSpace(children);
            }
        }

        List<AbstractExpression> buildChildren() {
            ArrayList<AbstractExpression> children = new ArrayList<AbstractExpression>();
            addChild(children);
            return children;
        }

        List<Boolean> buildCommas() {
            ArrayList<Boolean> children = new ArrayList<Boolean>();
            addComma(children);
            return children;
        }

        List<Boolean> buildSpaces() {
            ArrayList<Boolean> children = new ArrayList<Boolean>();
            addSpace(children);
            return children;
        }
    }
}
