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

import org.eclipse.persistence.jpa.jpql.AbstractEclipseLinkSemanticValidator.EclipseLinkOwningClauseVisitor;
import org.eclipse.persistence.jpa.jpql.parser.AbstractEclipseLinkExpressionVisitor;
import org.eclipse.persistence.jpa.jpql.parser.AbstractSelectClause;
import org.eclipse.persistence.jpa.jpql.parser.AsOfClause;
import org.eclipse.persistence.jpa.jpql.parser.CastExpression;
import org.eclipse.persistence.jpa.jpql.parser.ConnectByClause;
import org.eclipse.persistence.jpa.jpql.parser.DatabaseType;
import org.eclipse.persistence.jpa.jpql.parser.DatabaseTypeFactory;
import org.eclipse.persistence.jpa.jpql.parser.DefaultEclipseLinkJPQLGrammar;
import org.eclipse.persistence.jpa.jpql.parser.EclipseLinkExpressionVisitor;
import org.eclipse.persistence.jpa.jpql.parser.Expression;
import org.eclipse.persistence.jpa.jpql.parser.ExtractExpression;
import org.eclipse.persistence.jpa.jpql.parser.HierarchicalQueryClause;
import org.eclipse.persistence.jpa.jpql.parser.InExpression;
import org.eclipse.persistence.jpa.jpql.parser.InputParameter;
import org.eclipse.persistence.jpa.jpql.parser.JPQLGrammar;
import org.eclipse.persistence.jpa.jpql.parser.OrderSiblingsByClause;
import org.eclipse.persistence.jpa.jpql.parser.PatternValueBNF;
import org.eclipse.persistence.jpa.jpql.parser.RegexpExpression;
import org.eclipse.persistence.jpa.jpql.parser.SimpleSelectClause;
import org.eclipse.persistence.jpa.jpql.parser.SimpleSelectStatement;
import org.eclipse.persistence.jpa.jpql.parser.StartWithClause;
import org.eclipse.persistence.jpa.jpql.parser.StringExpressionBNF;
import org.eclipse.persistence.jpa.jpql.parser.TableExpression;
import org.eclipse.persistence.jpa.jpql.parser.TableVariableDeclaration;
import org.eclipse.persistence.jpa.jpql.parser.UnionClause;
import static org.eclipse.persistence.jpa.jpql.JPQLQueryProblemMessages.*;
import static org.eclipse.persistence.jpa.jpql.parser.Expression.*;

/**
 * This validator adds EclipseLink extension over what the JPA functional specification had defined.
 * <p>
 * Provisional API: This interface is part of an interim API that is still under development and
 * expected to change significantly before reaching stability. It is available at this early stage
 * to solicit feedback from pioneering adopters on the understanding that any code that uses this
 * API will almost certainly be broken (repeatedly) as the API evolves.
 *
 * @version 2.5
 * @since 2.4
 * @author Pascal Filion
 */
public class EclipseLinkGrammarValidator extends AbstractGrammarValidator
                                         implements EclipseLinkExpressionVisitor {

    private InExpressionVisitor inExpressionVisitor;
    private InExpressionWithNestedArrayVisitor inExpressionWithNestedArrayVisitor;

    /**
     * Creates a new <code>EclipseLinkGrammarValidator</code>.
     *
     * @param jpqlGrammar The {@link JPQLGrammar} that defines how the JPQL query was parsed
     */
    public EclipseLinkGrammarValidator(JPQLGrammar jpqlGrammar) {
        super(jpqlGrammar);
    }

    protected AbstractSingleEncapsulatedExpressionHelper<CastExpression> buildCastExpressionHelper() {
        return new AbstractSingleEncapsulatedExpressionHelper<CastExpression>(this) {
            @Override
            protected String encapsulatedExpressionInvalidKey(CastExpression expression) {
                return CastExpression_InvalidExpression;
            }
            @Override
            protected String encapsulatedExpressionMissingKey(CastExpression expression) {
                return CastExpression_MissingExpression;
            }
            @Override
            public String leftParenthesisMissingKey(CastExpression expression) {
                return CastExpression_MissingLeftParenthesis;
            }
            @Override
            public String rightParenthesisMissingKey(CastExpression expression) {
                return CastExpression_MissingRightParenthesis;
            }
        };
    }

    protected AbstractDoubleEncapsulatedExpressionHelper<DatabaseType> buildDatabaseTypeHelper() {
        return new AbstractDoubleEncapsulatedExpressionHelper<DatabaseType>(this) {
            @Override
            protected String firstExpressionInvalidKey() {
                return DatabaseType_InvalidFirstExpression;
            }
            @Override
            protected String firstExpressionMissingKey() {
                return DatabaseType_MissingFirstExpression;
            }
            @Override
            protected boolean hasComma(DatabaseType expression) {
                // If the second expression is not specified, then the comma is not needed
                return expression.hasComma() ||
                      !expression.hasSecondExpression();
            }
            @Override
            protected boolean hasFirstExpression(DatabaseType expression) {
                return !expression.hasLeftParenthesis() ||
                        expression.hasFirstExpression();
            }
            @Override
            public boolean hasLeftParenthesis(DatabaseType expression) {
                if (expression.hasLeftParenthesis()) {
                    return true;
                }
                // The parenthesis are optional unless one the following
                // items is specified, then '(' is required
                return !(expression.hasFirstExpression()  ||
                         expression.hasComma()            ||
                         expression.hasSecondExpression() ||
                         expression.hasRightParenthesis());
            }
            @Override
            public boolean hasRightParenthesis(DatabaseType expression) {
                if (expression.hasRightParenthesis()) {
                    return true;
                }
                // The parenthesis are optional unless one the following
                // items is specified, then ')' is required
                return !(expression.hasLeftParenthesis()  ||
                         expression.hasFirstExpression()  ||
                         expression.hasComma()            ||
                         expression.hasSecondExpression());
            }
            @Override
            protected boolean hasSecondExpression(DatabaseType expression) {
                return !expression.hasComma() ||
                        expression.hasSecondExpression();
            }
            @Override
            public String leftParenthesisMissingKey(DatabaseType expression) {
                return DatabaseType_MissingLeftParenthesis;
            }
            @Override
            protected String missingCommaKey() {
                return DatabaseType_MissingComma;
            }
            @Override
            public String rightParenthesisMissingKey(DatabaseType expression) {
                return DatabaseType_MissingRightParenthesis;
            }
            @Override
            protected String secondExpressionInvalidKey() {
                return DatabaseType_InvalidSecondExpression;
            }
            @Override
            protected String secondExpressionMissingKey() {
                return DatabaseType_MissingSecondExpression;
            }
        };
    }

    protected AbstractSingleEncapsulatedExpressionHelper<ExtractExpression> buildExtractExpressionHelper() {
        return new AbstractSingleEncapsulatedExpressionHelper<ExtractExpression>(this) {
            @Override
            protected String encapsulatedExpressionInvalidKey(ExtractExpression expression) {
                return ExtractExpression_InvalidExpression;
            }
            @Override
            protected String encapsulatedExpressionMissingKey(ExtractExpression expression) {
                return ExtractExpression_MissingExpression;
            }
            @Override
            public String leftParenthesisMissingKey(ExtractExpression expression) {
                return ExtractExpression_MissingLeftParenthesis;
            }
            @Override
            protected int lengthBeforeEncapsulatedExpression(ExtractExpression expression) {
                return expression.getDatePart().length() +
                       (expression.hasSpaceAfterDatePart() ? 1 : 0) +
                       (expression.hasFrom() ? 4 /* FROM */ : 0) +
                       (expression.hasSpaceAfterFrom() ? 1 : 0);
            }
            @Override
            public String rightParenthesisMissingKey(ExtractExpression expression) {
                return ExtractExpression_MissingRightParenthesis;
            }
        };
    }

    protected InExpressionVisitor buildInExpressionVisitor() {
        return new InExpressionVisitor();
    }

    protected InExpressionWithNestedArrayVisitor buildInExpressionWithNestedArrayVisitor() {
        return new InExpressionWithNestedArrayVisitor(this);
    }

    @Override
    protected LiteralVisitor buildLiteralVisitor() {
        return new EclipseLinkLiteralVisitor();
    }

    @Override
    protected OwningClauseVisitor buildOwningClauseVisitor() {
        return new EclipseLinkOwningClauseVisitor();
    }

    protected AbstractSingleEncapsulatedExpressionHelper<TableExpression> buildTableExpressionHelper() {
        return new AbstractSingleEncapsulatedExpressionHelper<TableExpression>(this) {
            @Override
            protected String encapsulatedExpressionInvalidKey(TableExpression expression) {
                return TableExpression_InvalidExpression;
            }
            @Override
            protected String encapsulatedExpressionMissingKey(TableExpression expression) {
                return TableExpression_MissingExpression;
            }
            @Override
            public String leftParenthesisMissingKey(TableExpression expression) {
                return TableExpression_MissingLeftParenthesis;
            }
            @Override
            public String rightParenthesisMissingKey(TableExpression expression) {
                return TableExpression_MissingRightParenthesis;
            }
        };
    }

    protected AbstractSingleEncapsulatedExpressionHelper<CastExpression> castExpressionHelper() {
        AbstractSingleEncapsulatedExpressionHelper<CastExpression> helper = getHelper(CAST);
        if (helper == null) {
            helper = buildCastExpressionHelper();
            registerHelper(CAST, helper);
        }
        return helper;
    }

    protected AbstractDoubleEncapsulatedExpressionHelper<DatabaseType> databaseTypeHelper() {
        AbstractDoubleEncapsulatedExpressionHelper<DatabaseType> helper = getHelper(DatabaseTypeFactory.ID);
        if (helper == null) {
            helper = buildDatabaseTypeHelper();
            registerHelper(DatabaseTypeFactory.ID, helper);
        }
        return helper;
    }

    protected AbstractSingleEncapsulatedExpressionHelper<ExtractExpression> extractExpressionHelper() {
        AbstractSingleEncapsulatedExpressionHelper<ExtractExpression> helper = getHelper(EXTRACT);
        if (helper == null) {
            helper = buildExtractExpressionHelper();
            registerHelper(EXTRACT, helper);
        }
        return helper;
    }

    protected InExpressionVisitor getInExpressionVisitor() {
        if (inExpressionVisitor == null) {
            inExpressionVisitor = buildInExpressionVisitor();
        }
        return inExpressionVisitor;
    }

    protected InExpressionWithNestedArrayVisitor getInExpressionWithNestedArray() {
        if (inExpressionWithNestedArrayVisitor == null) {
            inExpressionWithNestedArrayVisitor = buildInExpressionWithNestedArrayVisitor();
        }
        return inExpressionWithNestedArrayVisitor;
    }

    @Override
    protected EclipseLinkOwningClauseVisitor getOwningClauseVisitor() {
        return (EclipseLinkOwningClauseVisitor) super.getOwningClauseVisitor();
    }

    /**
     * Determines whether the persistence provider is EclipseLink or not.
     *
     * @return <code>true</code> if the persistence provider is EclipseLink; <code>false</code> otherwise
     */
    protected final boolean isEclipseLink() {
        return DefaultEclipseLinkJPQLGrammar.PROVIDER_NAME.equals(getProvider());
    }

    /**
     * Determines whether the subquery is part of an <code><b>IN</b></code> expression where the
     * left expression is a nested array.
     *
     * @param expression The {@link SimpleSelectClause} of the subquery
     * @return <code>true</code> if the subquery is in an <code><b>IN</b></code> expression and its
     * left expression is a nested array
     */
    protected boolean isInExpressionWithNestedArray(SimpleSelectClause expression) {
        InExpressionWithNestedArrayVisitor visitor = getInExpressionWithNestedArray();
        try {
            expression.accept(visitor);
            return visitor.valid;
        }
        finally {
            visitor.valid = false;
        }
    }

    @Override
    protected boolean isInputParameterInValidLocation(InputParameter expression) {
        return true;
    }

    @Override
    protected boolean isJoinFetchIdentifiable() {
        EclipseLinkVersion version = EclipseLinkVersion.value(getGrammar().getProviderVersion());
        return version.isNewerThanOrEqual(EclipseLinkVersion.VERSION_2_4);
    }

    @Override
    protected boolean isMultipleSubquerySelectItemsAllowed(SimpleSelectClause expression) {
        return isInExpressionWithNestedArray(expression);
    }

    protected boolean isOwnedByInExpression(Expression expression) {
        InExpressionVisitor visitor = getInExpressionVisitor();
        expression.accept(visitor);
        return visitor.expression != null;
    }

    /**
     * Determines whether the given {@link Expression} is a child of the <b>UNION</b> clause.
     *
     * @param expression The {@link Expression} to visit its parent hierarchy up to the clause
     * @return <code>true</code> if the first parent being a clause is the <b>UNION</b> clause;
     * <code>false</code> otherwise
     */
    protected boolean isOwnedByUnionClause(Expression expression) {
        EclipseLinkOwningClauseVisitor visitor = getOwningClauseVisitor();
        try {
            expression.accept(visitor);
            return visitor.unionClause != null;
        }
        finally {
            visitor.dispose();
        }
    }

    @Override
    protected boolean isSubqueryAllowedAnywhere() {
        EclipseLinkVersion version = EclipseLinkVersion.value(getProviderVersion());
        return version.isNewerThanOrEqual(EclipseLinkVersion.VERSION_2_4);
    }

    protected AbstractSingleEncapsulatedExpressionHelper<TableExpression> tableExpressionHelper() {
        AbstractSingleEncapsulatedExpressionHelper<TableExpression> helper = getHelper(TABLE);
        if (helper == null) {
            helper = buildTableExpressionHelper();
            registerHelper(TABLE, helper);
        }
        return helper;
    }

    @Override
    protected void validateAbstractSelectClause(AbstractSelectClause expression,
                                                boolean multipleSelectItemsAllowed) {

        // A subquery can have multiple select items if it is
        // - used as a "root" object in the top-level FROM clause
        // - defined in a UNION clause
        // - used in an IN expression
        // If the flag is false, then the SELECT clause is from a subquery
        if (!multipleSelectItemsAllowed) {
            Expression parent = expression.getParent();
            multipleSelectItemsAllowed = isOwnedByFromClause  (parent) ||
                                         isOwnedByUnionClause (parent) ||
                                         isOwnedByInExpression(parent);
        }

        super.validateAbstractSelectClause(expression, multipleSelectItemsAllowed);
    }

    @Override
    public void visit(AsOfClause expression) {
    }

    @Override
    public void visit(CastExpression expression) {

        // Wrong JPA version
        if (!isEclipseLink()) {
            addProblem(expression, CastExpression_InvalidJPAVersion);
        }
        else {

            validateAbstractSingleEncapsulatedExpression(expression, castExpressionHelper());

            // Database type
            if (expression.hasExpression() || expression.hasAs()) {

                // Missing database type
                if (!expression.hasDatabaseType()) {

                    int startPosition = position(expression) +
                                        4 /* CAST */ +
                                        (expression.hasLeftParenthesis() ? 1 : 0) +
                                        length(expression.getExpression()) +
                                        (expression.hasSpaceAfterExpression() ? 1 : 0) +
                                        (expression.hasAs() ? 2 : 0) +
                                        (expression.hasSpaceAfterAs() ? 1 : 0);

                    addProblem(expression, startPosition, CastExpression_MissingDatabaseType);
                }
                // Validate database type
                else {
                    expression.getDatabaseType().accept(this);
                }
            }
        }
    }

    @Override
    public void visit(ConnectByClause expression) {
        // TODO: 2.5
    }

    @Override
    public void visit(DatabaseType expression) {
        validateAbstractDoubleEncapsulatedExpression(expression, databaseTypeHelper());
    }

    @Override
    public void visit(ExtractExpression expression) {

        // Wrong JPA version
        if (!isEclipseLink()) {
            addProblem(expression, ExtractExpression_InvalidJPAVersion);
        }
        else {

                validateAbstractSingleEncapsulatedExpression(expression, extractExpressionHelper());

            // Missing date part
            if (expression.hasLeftParenthesis() && !expression.hasDatePart()) {

                int startPosition = position(expression) +
                                    7 /* EXTRACT */ +
                                    (expression.hasLeftParenthesis() ? 1 : 0);

                addProblem(expression, startPosition, ExtractExpression_MissingDatePart);
            }
        }
    }

    @Override
    public void visit(HierarchicalQueryClause expression) {
        // TODO: 2.5
    }

    @Override
    public void visit(OrderSiblingsByClause expression) {
        // TODO
    }

    @Override
    public void visit(RegexpExpression expression) {

        // Wrong JPA version
        if (!isEclipseLink()) {
            addProblem(expression, RegexpExpression_InvalidJPAVersion);
        }
        else {

            // Missing string expression
            if (!expression.hasStringExpression()) {

                int startPosition = position(expression);
                int endPosition   = startPosition;

                addProblem(
                    expression,
                    startPosition,
                    endPosition,
                    RegexpExpression_MissingStringExpression
                );
            }
            else {
                Expression stringExpression = expression.getStringExpression();

                // Invalid string expression
                if (!isValid(stringExpression, StringExpressionBNF.ID)) {

                    int startPosition = position(stringExpression);
                    int endPosition   = startPosition + length(stringExpression);

                    addProblem(
                        expression,
                        startPosition,
                        endPosition,
                        RegexpExpression_InvalidStringExpression
                    );
                }
                // Validate string expression
                else {
                    stringExpression.accept(this);
                }
            }

            // Missing pattern value
            if (!expression.hasPatternValue()) {

                int startPosition = position(expression) +
                                    length(expression.getStringExpression()) +
                                    (expression.hasSpaceAfterStringExpression() ? 1 : 0) +
                                    6 /* REGEXP */ +
                                    (expression.hasSpaceAfterIdentifier() ? 1 : 0);

                int endPosition = startPosition;

                addProblem(expression, startPosition, endPosition, RegexpExpression_MissingPatternValue);
            }
            else {
                Expression patternValue = expression.getStringExpression();

                // Invalid string expression
                if (!isValid(patternValue, PatternValueBNF.ID)) {

                    int startPosition = position(expression) +
                                        length(expression.getStringExpression()) +
                                        (expression.hasSpaceAfterStringExpression() ? 1 : 0) +
                                        6 /* REGEXP */ +
                                        (expression.hasSpaceAfterIdentifier() ? 1 : 0);

                    int endPosition = startPosition + length(patternValue);

                    addProblem(
                        expression,
                        startPosition,
                        endPosition,
                        RegexpExpression_InvalidPatternValue
                    );
                }
                // Validate pattern value
                else {
                    patternValue.accept(this);
                }
            }
        }
    }

    @Override
    public void visit(StartWithClause expression) {
        // TODO: 2.5
    }

    @Override
    public void visit(TableExpression expression) {
        validateAbstractSingleEncapsulatedExpression(expression, tableExpressionHelper());
    }

    @Override
    public void visit(TableVariableDeclaration expression) {

        // Wrong JPA version
        if (!isEclipseLink()) {
            addProblem(expression, TableVariableDeclaration_InvalidJPAVersion);
        }
        else {

            TableExpression tableExpression = expression.getTableExpression();

            // Validate the table expression
            tableExpression.accept(this);

            // The identification variable is missing
            if (!expression.hasIdentificationVariable()) {

                int startPosition = position(expression) +
                                    length(tableExpression) +
                                    (expression.hasSpaceAfterTableExpression() ? 1 : 0) +
                                    (expression.hasAs() ? 2 : 0) +
                                    (expression.hasSpaceAfterAs() ? 1 : 0);

                addProblem(expression, startPosition, TableVariableDeclaration_MissingIdentificationVariable);
            }
            // Validate the identification variable
            else {
                expression.getIdentificationVariable().accept(this);
            }
        }
    }

    @Override
    public void visit(UnionClause expression) {

        // Wrong JPA version
        if (!isEclipseLink()) {
            addProblem(expression, UnionClause_InvalidJPAVersion);
        }
        // Missing subquery
        else if (!expression.hasQuery()) {

            int startPosition = position(expression) +
                                expression.getIdentifier().length() +
                                (expression.hasSpaceAfterIdentifier() ? 1 : 0) +
                                (expression.hasAll() ? 3 : 0) +
                                (expression.hasSpaceAfterAll() ? 1 : 0);

            addProblem(expression, startPosition, UnionClause_MissingExpression);
        }
        // Validate the subquery
        else {
            expression.getQuery().accept(this);
        }
    }

    // Made static for performance reasons.
    protected static class InExpressionVisitor extends AbstractEclipseLinkExpressionVisitor {

        protected InExpression expression;

        /**
         * Default constructor.
         */
        protected InExpressionVisitor() {
        }

        @Override
        public void visit(InExpression expression) {
            this.expression = expression;
        }
    }

    // Made static final for performance reasons.
    protected static final class InExpressionWithNestedArrayVisitor extends AbstractEclipseLinkExpressionVisitor {

        private final EclipseLinkGrammarValidator visitor;

        protected InExpressionWithNestedArrayVisitor(EclipseLinkGrammarValidator visitor) {
            this.visitor = visitor;
        }

        /**
         * Determines whether the left expression of an <code><b>IN</b></code> expression is a nested
         * array when the <code><b>IN</b></code> item is a subquery.
         */
        public boolean valid;

        @Override
        public void visit(InExpression expression) {
            valid = visitor.isNestedArray(expression.getExpression());
        }

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

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