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

    @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());
    }

    @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();
    }

    @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();
    }

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

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

    @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);
    }

    @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();
    }

    @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;
    }

    @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);
    }

    @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);
    }

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

    @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);

    @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;
        }
    }
}
