/*
 * 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.util.Collection;
import java.util.List;
import org.eclipse.persistence.jpa.jpql.ExpressionTools;
import org.eclipse.persistence.jpa.jpql.WordParser;

/**
 * A null comparison tests whether or not the single-valued path expression or input parameter is a
 * <b>NULL</b> value.
 *
 * <div><b>BNF:</b> <code>null_comparison_expression ::= {single_valued_path_expression | input_parameter} IS [NOT] NULL</code></div>
 *
 * @version 2.5
 * @since 2.3
 * @author Pascal Filion
 */
public final class NullComparisonExpression extends AbstractExpression {

    /**
     * The expression tested for being <code>null</code> or not.
     */
    private AbstractExpression expression;

    /**
     * The actual <b>IS</b> identifier found in the string representation of the JPQL query.
     */
    private String isIdentifier;

    /**
     * The actual <b>IS</b> identifier found in the string representation of the JPQL query.
     */
    private String notIdentifier;

    /**
     * The actual <b>NULL</b> identifier found in the string representation of the JPQL query.
     */
    private String nullIdentifier;

    /**
     * Creates a new <code>NullComparisonExpression</code>.
     *
     * @param parent The parent of this expression
     * @param expression The expression before the identifier
     */
    public NullComparisonExpression(AbstractExpression parent,
                                    String identifier,
                                    AbstractExpression expression) {

        super(parent, identifier);
        this.expression = expression;

        if (expression != null) {
            expression.setParent(this);
        }
    }

    @Override
    public void accept(ExpressionVisitor visitor) {
        visitor.visit(this);
    }

    @Override
    public void acceptChildren(ExpressionVisitor visitor) {
        getExpression().accept(visitor);
    }

    @Override
    protected void addChildrenTo(Collection<Expression> children) {
        children.add(getExpression());
    }

    @Override
    protected void addOrderedChildrenTo(List<Expression> children) {

        // Expression
        if (hasExpression()) {
            children.add(expression);
            children.add(buildStringExpression(SPACE));
        }

        // Identifier
        children.add(buildStringExpression(getIdentifier()));
    }

    @Override
    public JPQLQueryBNF findQueryBNF(Expression expression) {

        if (this.expression == expression) {
            return expression.getQueryBNF();
        }

        return super.findQueryBNF(expression);
    }

    /**
     * Returns the actual <b>IS</b> found in the string representation of the JPQL query, which has
     * the actual case that was used.
     *
     * @return The <b>IS</b> identifier that was actually parsed, or an empty string if it was not
     * parsed
     */
    public String getActualIsIdentifier() {
        return (isIdentifier != null) ? isIdentifier : ExpressionTools.EMPTY_STRING;
    }

    /**
     * Returns the actual <b>Not</b> found in the string representation of the JPQL query, which has
     * the actual case that was used.
     *
     * @return The <b>NOT</b> identifier that was actually parsed, or an empty string if it was not parsed
     */
    public String getActualNotIdentifier() {
        return (notIdentifier != null) ? notIdentifier : ExpressionTools.EMPTY_STRING;
    }

    /**
     * Returns the actual <b>NULL</b> found in the string representation of the JPQL query, which has
     * the actual case that was used.
     *
     * @return The <b>NULL</b> identifier that was actually parsed
     */
    public String getActualNullIdentifier() {
        return nullIdentifier;
    }

    /**
     * Returns the expression being tested for being <code>null</code>.
     *
     * @return Either the parsed expression or the <code>null</code>-expression
     */
    public Expression getExpression() {
        if (expression == null) {
            expression = buildNullExpression();
        }
        return expression;
    }

    /**
     * Returns the identifier for this expression that may include <b>NOT</b> if it was parsed.
     *
     * @return Either <b>IS NULL</b> or <b>IS NOT NULL</b>
     */
    public String getIdentifier() {
        return (notIdentifier != null) ? IS_NOT_NULL : IS_NULL;
    }

    @Override
    public JPQLQueryBNF getQueryBNF() {
        return getQueryBNF(NullComparisonExpressionBNF.ID);
    }

    /**
     * Determines whether the expression preceding the identifier was parsed.
     *
     * @return <code>true</code> the expression preceding the identifier was parsed;
     * <code>false</code> otherwise
     */
    public boolean hasExpression() {
        return expression != null &&
              !expression.isNull();
    }

    /**
     * Determines whether <b>NOT</b> is used in the query.
     *
     * @return <code>true</code> if <b>NOT</b> is present in the query; <code>false</code> otherwise
     */
    public boolean hasNot() {
        return notIdentifier != null;
    }

    @Override
    protected void parse(WordParser wordParser, boolean tolerant) {

        // 'IS'
        isIdentifier = wordParser.moveForward(IS);

        wordParser.skipLeadingWhitespace();

        // 'NOT'
        if (wordParser.startsWithIdentifier(NOT)) {
            notIdentifier = wordParser.moveForward(NOT);
            wordParser.skipLeadingWhitespace();
            setText(IS_NOT_NULL);
        }
        else {
            setText(IS_NULL);
        }

        // 'NULL'
        nullIdentifier = wordParser.moveForward(NULL);
    }

    @Override
    protected void toParsedText(StringBuilder writer, boolean actual) {

        if (hasExpression()) {
            expression.toParsedText(writer, actual);
            writer.append(SPACE);
        }

        if (actual) {

            writer.append(isIdentifier);
            writer.append(SPACE);

            if (notIdentifier != null) {
                writer.append(notIdentifier);
                writer.append(SPACE);
            }

            writer.append(nullIdentifier);
        }
        else {
            writer.append(getIdentifier());
        }
    }
}
