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

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import org.eclipse.persistence.jpa.jpql.utility.filter.Filter;
import org.eclipse.persistence.jpa.jpql.utility.filter.NullFilter;
import org.eclipse.persistence.jpa.jpql.utility.iterable.ArrayIterable;

/**
 * <p>This defines a single Backus-Naur Form (BNF) of the JPQL grammar. The Java Persistence functional
 * specifications are:</p>
 * <ul>
 * <li>{@link JPQLGrammar1_0}: <a href="http://jcp.org/en/jsr/detail?id=220">JSR 220: Enterprise JavaBeans&trade; version 3.0</a></li>
 * <li>{@link JPQLGrammar2_0}: <a href="http://jcp.org/en/jsr/detail?id=317">JSR 317: Java&trade; Persistence 2.0</a></li>
 * <li>{@link JPQLGrammar2_1}: <a href="http://jcp.org/en/jsr/detail?id=338">JSR 338: Java&trade; Persistence 2.1</a></li>
 * </ul>
 *
 * <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.</p>
 *
 * @version 2.5.1
 * @since 2.3
 * @author Pascal Filion
 */
@SuppressWarnings("nls")
public abstract class JPQLQueryBNF {

    /**
     * Caches the {@link ExpressionFactory} mapped by their the JPQL identifier registered with those
     * {@link ExpressionFactory}.
     */
    private Map<String, ExpressionFactory> cachedExpressionFactories;

    /**
     * Caches the collection of unique identifiers of the {@link ExpressionFactory} registered with
     * this BNF rule.
     */
    private String[] cachedExpressionFactoryIds;

    /**
     * The list of JPQL identifiers that are known by this BNF rule and its children, they are
     * retrieved by scanning the list of {@link ExpressionFactory} registered with this BNF rule
     * and its children.
     */
    private String[] cachedIdentifiers;

    /**
     * Caches the children of this BNF rule (which actually includes this one as well).
     */
    private JPQLQueryBNF[] childQueryBNFs;

    /**
     * The children BNF of this one.
     */
    private List<String> children;

    /**
     * Determines whether this BNF has child BNFs registered only to properly parse a query or if the
     * child BNFs are part of the BNF. An example if a compound BNF is {@link BetweenExpressionBNF},
     * it registers a series of children BNFs but they shouldn't be used to determine if they are
     * part of that BNF since the comparator identifiers are.
     */
    private boolean compound;

    /**
     * The list of unique identifiers for the {@link ExpressionFactory} that are registered with this BNF rule.
     */
    private List<String> expressionFactoryIds;

    /**
     * The {@link ExpressionRegistry} with which this {@link JPQLQueryBNF} was registered.
     */
    private ExpressionRegistry expressionRegistry;

    /**
     * The unique identifier of the {@link JPQLQueryBNF} to use in the last resort.
     */
    private String fallbackBNFId;

    /**
     * The unique identifier of the {@link ExpressionFactory} to use when no other factories can be
     * used automatically.
     */
    private String fallbackExpressionFactoryId;

    /**
     * Caches the property since any BNF rule is static.
     */
    private Boolean handleAggregate;

    /**
     * Caches the property since any BNF rule is static.
     */
    private Boolean handleCollection;

    /**
     * Determines whether this BNF handles parsing a nested array or not.
     */
    private boolean handleNestedArray;

    /**
     * This flag can be used to determine if this BNF handles parsing a sub-expression, i.e. an
     * expression encapsulated by parenthesis. See {@link #setHandleSubExpression(boolean)} for more
     * details.
     */
    private boolean handleSubExpression;

    /**
     * The unique identifier of this BNF rule.
     */
    private String id;

    /**
     * Caches the children of this BNF rule (which actually includes this one as well) but do not
     * includes BNF rules that are used for compounding a rule.
     */
    private JPQLQueryBNF[] nonCompoundChildren;

    /**
     * Only keep one instance of the {@link Filter} used when initializing {@link #nonCompoundChildren} JPQLQueryBNF.
     * This should help with performance since the filter won't be created for each <code>JPQLQueryBNF</code>.
     */
    private static final Filter<JPQLQueryBNF> nonCompoundFilter = buildNonCompoundFilter();

    /**
     * Creates a new <code>JPQLQueryBNF</code>.
     *
     * @param id The unique identifier of this BNF rule
     * @exception NullPointerException The given unique identifier cannot be <code>null</code>
     */
    protected JPQLQueryBNF(String id) {
        super();
        initialize(id);
    }

    private static Filter<JPQLQueryBNF> buildNonCompoundFilter() {
        return new Filter<JPQLQueryBNF>() {
            @Override
            public boolean accept(JPQLQueryBNF queryBNF) {
                return !queryBNF.isCompound();
            }
        };
    }

    /**
     * Adds to the given set the child BNF rules and requests them to add their children as long as
     * they have not been traversed already.
     *
     * @param queryBNFs The set to add the child BNF rules
     * @param filter The {@link Filter} determines if the children of a given BNF should be added
     */
    private void addChildren(Set<JPQLQueryBNF> queryBNFs, Filter<JPQLQueryBNF> filter) {

        // null children means no child JPQLQueryBNF was registered
        if (children != null) {

            for (String id : children) {
                JPQLQueryBNF queryBNF = expressionRegistry.getQueryBNF(id);

                if (queryBNFs.add(queryBNF) && filter.accept(queryBNF)) {
                    queryBNF.addChildren(queryBNFs, filter);
                }
            }
        }
    }

    private JPQLQueryBNF[] buildChildren(Filter<JPQLQueryBNF> filter) {

        Set<JPQLQueryBNF> queryBNFs = new HashSet<JPQLQueryBNF>();
        queryBNFs.add(this);
        addChildren(queryBNFs, filter);

        JPQLQueryBNF[] children = new JPQLQueryBNF[queryBNFs.size()];
        queryBNFs.toArray(children);

        return children;
    }

    private void calculateExpressionFactories() {

        synchronized (this) {

            if (cachedExpressionFactories == null) {

                Map<String, ExpressionFactory> factories = new HashMap<String, ExpressionFactory>();

                // Caches the ExpressionFactory mapped by all the JPQL identifiers that
                // are registered for that ExpressionFactory
                for (String expressionFactoryId : getExpressionFactoryIdsImp()) {
                    ExpressionFactory expressionFactory = expressionRegistry.getExpressionFactory(expressionFactoryId);

                    for (String identifier : expressionFactory.identifiers()) {
                        factories.put(identifier, expressionFactory);
                    }
                }

                cachedIdentifiers = new String[factories.size()];
                factories.keySet().toArray(cachedIdentifiers);

                cachedExpressionFactories = factories;
            }
        }
    }

    private void calculateExpressionFactoryIds(Set<JPQLQueryBNF> queryBNFs, Set<String> factoryIds) {

        if (expressionFactoryIds != null) {
            factoryIds.addAll(expressionFactoryIds);
        }

        for (JPQLQueryBNF queryBNF : getChildren()) {
            if ((queryBNF != this) && (queryBNFs.add(queryBNF))) {
                queryBNF.calculateExpressionFactoryIds(queryBNFs, factoryIds);
            }
        }
    }

    private boolean calculateHandleAggregate(Set<JPQLQueryBNF> queryBNFs) {

        if (handleAggregate != null) {
            return handleAggregate;
        }

        for (JPQLQueryBNF queryBNF : getChildren()) {
            if ((queryBNF != this) && queryBNFs.add(queryBNF)) {
                boolean result = queryBNF.calculateHandleAggregate(queryBNFs);
                if (result) {
                    return true;
                }
            }
        }

        return false;
    }

    private boolean calculateHandleCollection(Set<JPQLQueryBNF> queryBNFs) {

        if (handleCollection != null) {
            return handleCollection;
        }

        for (JPQLQueryBNF queryBNF : getChildren()) {
            if ((queryBNF != this) && queryBNFs.add(queryBNF)) {
                boolean result = queryBNF.calculateHandleCollection(queryBNFs);
                if (result) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * Returns the set of all the query BNFs that are part of this BNF. The set always include this
     * BNF as well.
     *
     * @return The children BNFs describing this BNF rule
     */
    public Iterable<JPQLQueryBNF> children() {
        return new ArrayIterable<JPQLQueryBNF>(getChildren());
    }

    private JPQLQueryBNF[] getChildren() {

        // No need to synchronize if the list of children was calculated
        if (childQueryBNFs != null) {
            return childQueryBNFs;
        }

        // Synchronize to make sure only one thread populates the list of children
        synchronized (this) {
            if (childQueryBNFs == null) {
                childQueryBNFs = buildChildren(NullFilter.<JPQLQueryBNF>instance());
            }
        }

        return childQueryBNFs;
    }

    /**
     * Retrieves the {@link ExpressionFactory} that is associated with the given identifier, if the
     * given string is indeed a JPQL identifier.
     *
     * @param identifier The JPQL identifier (in theory) that is used to retrieve the factory
     * responsible to parse a portion of the query starting with that identifier
     * @return The {@link ExpressionFactory} responsible to parse a portion of the query starting
     * with the given identifier; <code>null</code> if nothing was registered for it
     */
    public ExpressionFactory getExpressionFactory(String identifier) {

        // No need to synchronize if the map was calculated
        if (cachedExpressionFactories != null) {
            return cachedExpressionFactories.get(identifier.toUpperCase(Locale.ROOT));
        }

        // Synchronize to make sure only one thread populates the list of JPQL identifiers
        calculateExpressionFactories();

        return cachedExpressionFactories.get(identifier.toUpperCase(Locale.ROOT));
    }

    /**
     * Returns the unique identifiers of the {@link ExpressionFactory} handled by this BNF rule,
     * which includes those from the children as well.
     *
     * @return The list of unique identifiers of the {@link ExpressionFactory} registered with this
     * BNF rule and with its children
     */
    public Iterable<String> getExpressionFactoryIds() {
        return new ArrayIterable<String>(getExpressionFactoryIdsImp());
    }

    private String[] getExpressionFactoryIdsImp() {

        // No need to synchronize if the list of cached ExpressionFactory was calculated
        if (cachedExpressionFactoryIds != null) {
            return cachedExpressionFactoryIds;
        }

        // Synchronize to make sure only one thread populates the list of ExpressionFactory IDs
        synchronized (this) {

            if (cachedExpressionFactoryIds == null) {

                Set<JPQLQueryBNF> queryBNFs = new HashSet<JPQLQueryBNF>();
                Set<String> factoryIds = new HashSet<String>();
                calculateExpressionFactoryIds(queryBNFs, factoryIds);

                cachedExpressionFactoryIds = new String[factoryIds.size()];
                factoryIds.toArray(cachedExpressionFactoryIds);
            }
        }

        return cachedExpressionFactoryIds;
    }

    /**
     * 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
     */
    public ExpressionRegistry getExpressionRegistry() {
        return expressionRegistry;
    }

    /**
     * When parsing the query and no {@link JPQLQueryBNF JPQLQueryBNFs} can help to parse the query,
     * then it will fall back on this one.
     *
     * @return The unique identifier of the {@link JPQLQueryBNF} to use in the last resort
     */
    public String getFallbackBNFId() {
        return fallbackBNFId;
    }

    /**
     * Returns the unique identifier of the {@link ExpressionFactory} to use when the fall back BNF
     * ID is not <code>null</code>. This will be used to parse a portion of the query when the
     * registered {@link ExpressionFactory expression factories} cannot parse it.
     * <p>
     * Note: This method is only called if {@link #getFallbackBNFId()} does not return <code>null</code>.
     *
     * @return The unique identifier of the {@link ExpressionFactory}
     */
    public String getFallbackExpressionFactoryId() {
        return fallbackExpressionFactoryId;
    }

    /**
     * Returns the unique identifier of this {@link JPQLQueryBNF}.
     *
     * @return The identifier used to register this {@link JPQLQueryBNF} with {@link AbstractExpression}
     */
    public String getId() {
        return id;
    }

    /**
     * Retrieves the JPQL identifiers that are supported by this BNF rule. The JPQL identifiers are
     * retrieved by scanning the {@link ExpressionFactory} registered with this BNF rule and the
     * child BNF rules.
     *
     * @return The list of JPQL identifiers that are supported by this BNF
     */
    public Iterable<String> getIdentifiers() {

        // No need to synchronize if the cached JPQL identifiers was calculated
        // Note: it could be possible cachedIdentifiers was instantiated but the list of JPQL
        // identifiers has not been copied from cachedExpressionFactoryIds yet.
        // cachedExpressionFactoryIds is set at the end of the method, insuring proper initialization
        if (cachedExpressionFactoryIds != null) {
            return new ArrayIterable<String>(cachedIdentifiers);
        }

        // Synchronize to make sure only one thread populates the list of JPQL identifiers
        calculateExpressionFactories();

        return new ArrayIterable<String>(cachedIdentifiers);
    }

    /**
     * Determines whether the {@link Expression} handles a collection of sub-expressions that
     * are aggregated by logical or arithmetic operators.
     *
     * @return <code>true</code> if the sub-expression to parse might have several logical and/or
     * arithmetic expressions; <code>false</code> otherwise
     */
    public boolean handleAggregate() {

        // No need to synchronize if the property was calculated
        if (handleAggregate != null) {
            return handleAggregate;
        }

        // Synchronize to make sure only one thread calculates it
        synchronized (this) {
            if (handleAggregate == null) {
                Set<JPQLQueryBNF> children = new HashSet<JPQLQueryBNF>();
                handleAggregate = calculateHandleAggregate(children);
            }
        }

        return handleAggregate;
    }

    /**
     * Determines whether the <code>Expression</code> handles a collection of sub-expressions that
     * are separated by commas.
     *
     * @return <code>true</code> if the sub-expression to parse might have several sub-expressions
     * separated by commas; <code>false</code> otherwise
     */
    public boolean handleCollection() {

        // No need to synchronize if the property was calculated
        if (handleCollection != null) {
            return handleCollection;
        }

        // Synchronize to make sure only one thread calculates it
        synchronized (this) {
            if (handleCollection == null) {
                Set<JPQLQueryBNF> children = new HashSet<JPQLQueryBNF>();
                handleCollection = calculateHandleCollection(children);
            }
        }

        return handleCollection;
    }

    /**
     * @since 2.5
     */
    public boolean handlesNestedArray() {
        return handleNestedArray;
    }

    /**
     * Determines whether this BNF handles parsing a sub-expression, i.e. parsing an expression
     * encapsulated by parenthesis. See {@link #setHandleSubExpression(boolean)} for more details.
     *
     * @return <code>true</code> if this BNF handles parsing a sub-expression; <code>false</code> otherwise
     */
    public boolean handleSubExpression() {
        return handleSubExpression;
    }

    /**
     * Determines whether the BNF with the given ID is part of this BNF or not.
     *
     * @param queryBNFId The unique identifier of the BNF rule to check if it's a child of this one
     * @return <code>true</code> if the BNF with the given ID is
     * @since 2.5.1
     */
    public boolean hasChild(String queryBNFId) {

        for (JPQLQueryBNF child : getChildren()) {
            if (child.getId().equals(queryBNFId)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Determines if this query BNF support the given word, which can be an identifier.
     *
     * @param word A word that could be a JPQL identifier or anything else
     * @return <code>true</code> if the given word is a JPQL identifier and it is supported by this
     * BNF; <code>false</code> otherwise
     */
    public boolean hasIdentifier(String word) {

        // No need to synchronize if the map of cached ExpressionFactory was calculated
        if (cachedExpressionFactories != null) {
            return cachedExpressionFactories.containsKey(word);
        }

        // Synchronize to make sure only one thread calculates it
        calculateExpressionFactories();

        return cachedExpressionFactories.containsKey(word);
    }

    /**
     * Initializes this BNF by registering child {@link JPQLQueryBNF JPQLQueryBNFs} and {@link
     * ExpressionFactory ExpressionFactories}.
     */
    protected void initialize() {
    }

    /**
     * Initializes this <code>JPQLQueryBNF</code>.
     *
     * @param id The unique identifier of this BNF rule
     * @exception NullPointerException The given unique identifier cannot be <code>null</code>
     */
    private void initialize(String id) {

        if (id == null) {
            throw new NullPointerException("The unique identifier of this JPQLQueryBNF cannot be null");
        }

        this.id = id;
        initialize();
    }

    /**
     * Determines whether this BNF has child BNFs registered only to properly parse a query or if the
     * child BNFs are part of the BNF. An example if a compound BNF is {@link BetweenExpressionBNF},
     * it registers a series of children BNFs but they shouldn't be used to determine if they are
     * part of that BNF since the comparator identifiers are.
     *
     * @return <code>false</code> by default
     */
    public boolean isCompound() {
        return compound;
    }

    /**
     * Returns the set of all the query BNFs that are part of this BNF. The set always include this
     * BNF as well.
     *
     * @return The children BNFs describing this BNF rule. The set excludes BNF rules that are used
     * to complete a BNF, such as the BNF rules defined for <b>BETWEEN</b> since they are required
     * to properly parse the query
     */
    public Iterable<JPQLQueryBNF> nonCompoundChildren() {

        // No need to synchronize if the list of child BNFs (non-compound) was calculated
        if (nonCompoundChildren != null) {
            return new ArrayIterable<JPQLQueryBNF>(nonCompoundChildren);
        }

        // Synchronize to make sure only one thread populates the list of child BNFs (non-compound)
        synchronized (this) {
            if (nonCompoundChildren == null) {
                nonCompoundChildren = buildChildren(nonCompoundFilter);
            }
        }

        return new ArrayIterable<JPQLQueryBNF>(nonCompoundChildren);
    }

    /**
     * Registers the unique identifier of the BNF rule as a child of this BNF rule.
     *
     * @param queryBNFId The unique identifier of the BNF rule to add as a child
     * @exception NullPointerException The <code>queryBNFId</code> cannot be <code>null</code>
     */
    protected final void registerChild(String queryBNFId) {

        if (queryBNFId == null) {
            throw new NullPointerException("The queryBNFId cannot be null");
        }

        if (children == null) {
            children = new LinkedList<String>();
        }

        children.add(queryBNFId);
    }

    /**
     * Registers a unique identifier of the {@link ExpressionFactory} to register with this BNF rule.
     *
     * @param expressionFactoryId The unique identifier of the {@link ExpressionFactory}
     * @exception NullPointerException The <code>expressionFactoryId</code> cannot be <code>null</code>
     */
    protected final void registerExpressionFactory(String expressionFactoryId) {

        if (expressionFactoryId == null) {
            throw new NullPointerException("The expressionFactoryId cannot be null");
        }

        if (expressionFactoryIds == null) {
            expressionFactoryIds = new LinkedList<String>();
        }

        expressionFactoryIds.add(expressionFactoryId);
    }

    /**
     * Determines whether this BNF has child BNFs registered only to properly parse a query or if the
     * child BNFs are part of the BNF. An example if a compound BNF is {@link BetweenExpressionBNF},
     * it registers a series of children BNFs but they shouldn't be used to determine if they are
     * part of that BNF since the comparator identifiers are.
     *
     * @param compound <code>true</code> if this BNF represents a compound BNF and its children are
     * not part of this BNF but only to support compound expression; <code>false</code> otherwise
     */
    public void setCompound(boolean compound) {
        this.compound = compound;
    }

    /**
     * Sets the backpointer to the {@link ExpressionRegistry} with which this {@link JPQLQueryBNF}
     * was registered.
     *
     * @param expressionRegistry The registry for a given JPQL grammar
     */
    final void setExpressionRegistry(ExpressionRegistry expressionRegistry) {
        this.expressionRegistry = expressionRegistry;
    }

    /**
     * When parsing the query and no {@link JPQLQueryBNF JPQLQueryBNFs} can help to parse the query,
     * then it will fall back on the given one.
     *
     * @param fallbackBNFId The unique identifier of the {@link JPQLQueryBNF} to use in the last resort
     */
    public void setFallbackBNFId(String fallbackBNFId) {
        this.fallbackBNFId = fallbackBNFId;
    }

    /**
     * Sets the unique identifier of the {@link ExpressionFactory} to use when the fall back BNF
     * ID is not <code>null</code>. This will be used to parse a portion of the query when the
     * registered {@link ExpressionFactory expression factories} cannot parse it.
     * <p>
     * Note: This method is only called if {@link #getFallbackBNFId()} does not return <code>null</code>.
     *
     * @param fallbackExpressionFactoryId The unique identifier of the {@link ExpressionFactory}
     */
    public void setFallbackExpressionFactoryId(String fallbackExpressionFactoryId) {
        this.fallbackExpressionFactoryId = fallbackExpressionFactoryId;
    }

    /**
     * Sets whether the {@link Expression} handles a collection of sub-expressions that are
     * aggregated by logical or arithmetic operators.
     *
     * @param handleAggregate <code>true</code> if the sub-expression to parse might have several
     * logical and/or arithmetic expressions; <code>false</code> otherwise
     */
    public void setHandleAggregate(boolean handleAggregate) {
        this.handleAggregate = handleAggregate;
    }

    /**
     * Sets whether the <code>Expression</code> handles a collection of sub-expressions that are
     * separated by commas.
     *
     * @param handleCollection <code>true</code> if the sub-expression to parse might have several
     * sub-expressions separated by commas; <code>false</code> otherwise
     */
    public void setHandleCollection(boolean handleCollection) {
        this.handleCollection = handleCollection;
    }

    /**
     * Sets whether this BNF supports nested array or not. A nested array is a sub-expression with
     * its child being a collection expression: (item_1, item_2, ..., item_n).
     *
     * @param handleNestedArray <code>true</code> if the expression represented by this BNF can be
     * a nested array; <code>false</code> otherwise
     * @since 2.5
     */
    public void setHandleNestedArray(boolean handleNestedArray) {
        this.handleNestedArray = handleNestedArray;
    }

    /**
     * Sets whether this BNF handles parsing a sub-expression, i.e. parsing an expression
     * encapsulated by parenthesis. Which in fact would be handled by the fallback {@link
     * ExpressionFactory}. The default behavior is to not handle it.
     * <p>
     * A good example for using this option is when an {@link Expression} cannot use any {@link
     * ExpressionFactory} for creating a child object, parsing will use the fallback {@link
     * ExpressionFactory}, if one was specified. So when this is set to <code>true</code>, the
     * fallback {@link ExpressionFactory} will be immediately invoked.
     * <p>
     * Let's say we want to parse "SELECT e FROM (SELECT a FROM Address a) e", {@link FromClause}
     * cannot use a factory for parsing the entity name (that's what usually the <code>FROM</code>
     * clause has) so it uses the fallback factory to create {@link IdentificationVariableDeclaration}.
     * Then <code>IdentificationVariableDeclaration</code> also cannot use any factory to create its
     * child object so it uses the fallback factory to create {@link RangeVariableDeclaration}.
     * By changing the status of for handling the sub-expression for the BNFs for those objects, then
     * a subquery can be created by <code>RangeVariableDeclaration</code>.
     *
     * <pre><code>FromClause
     *  |- IdentificationVariableDeclaration
     *       |- RangeVariableDeclaration
     *            |- SubExpression(subquery)</code></pre>
     *
     * In order to get this working, the following would have to be done into the grammar:
     *
     * <pre><code> public class MyJPQLGrammar extends AbstractJPQLGrammar {
     *   &#64;Override
     *   protected void initializeBNFs() {
     *      setHandleSubExpression(InternalFromClauseBNF.ID,                true);
     *      setHandleSubExpression(InternalSimpleFromClauseBNF.ID,          true);
     *      setHandleSubExpression(IdentificationVariableDeclarationBNF.ID, true);
     *      setHandleSubExpression(RangeVariableDeclarationBNF.ID,          true);
     *   }
     * }</code></pre>
     *
     * @param handleSubExpression <code>true</code> to let the creation of a sub-expression be
     * created by the fallback {@link ExpressionFactory} registered with this BNF; <code>false</code>
     * otherwise (which is the default value)
     */
    public void setHandleSubExpression(boolean handleSubExpression) {
        this.handleSubExpression = handleSubExpression;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(getClass().getSimpleName());
        toString(sb);
        return sb.toString();
    }

    /**
     * Adds to the given builder more information about this {@link JPQLQueryBNF}.
     *
     * @param sb The builder used to add information about this class
     */
    protected void toString(StringBuilder sb) {
        sb.append("(");
        sb.append(id);
        sb.append(")\n\nidentifiers=");
        sb.append(getIdentifiers());
        sb.append("\n\nexpressionFactories=");
        sb.append(Arrays.toString(getExpressionFactoryIdsImp()));
    }
}
