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

package org.eclipse.persistence.jpa.tests.jpql;

import org.eclipse.persistence.jpa.jpql.tools.model.DefaultActualJPQLQueryFormatter;
import org.eclipse.persistence.jpa.jpql.tools.model.DefaultJPQLQueryFormatter;
import org.eclipse.persistence.jpa.jpql.tools.model.IJPQLQueryBuilder;
import org.eclipse.persistence.jpa.jpql.tools.model.IJPQLQueryFormatter;
import org.eclipse.persistence.jpa.jpql.tools.model.IJPQLQueryFormatter.IdentifierStyle;
import org.eclipse.persistence.jpa.jpql.tools.model.query.JPQLQueryStateObject;
import org.eclipse.persistence.jpa.jpql.tools.model.query.SelectStatementStateObject;
import org.eclipse.persistence.jpa.tests.jpql.tools.model.IJPQLQueryBuilderTestHelper;
import org.junit.Test;
import static org.junit.Assert.*;

/**
 * Illustrates possible bugs in the Hermes 2.0 parser.
 */
@UniqueSignature
@SuppressWarnings("nls")
public final class HermesBugsTest extends JPQLCoreTest {

    @IJPQLQueryBuilderTestHelper
    private IJPQLQueryBuilder queryBuilder;

    /**
     * missing space before WHERE statement
     */
    @Test
    public void testAddWhereClauseMissingSpace() throws Exception {

        String jpql = "SELECT a FROM Artifact a";
        JPQLQueryStateObject so = queryBuilder.buildStateObject(getPersistenceUnit(), jpql, true);

        SelectStatementStateObject selectSO = (SelectStatementStateObject) so.getQueryStatement();
        assertFalse(selectSO.hasWhereClause());
        selectSO.addWhereClause("a.relativeURI LIKE '%bar'");

        IJPQLQueryFormatter formatter = new DefaultActualJPQLQueryFormatter(false);
        assertEquals("SELECT a FROM Artifact a WHERE a.relativeURI LIKE '%bar'", formatter.toString(so));
        // instead we get
        // SELECT a FROM Artifact aWHERE a.relativeURI LIKE '%bar'
        // this only happens with DefaultActualJPQLQueryFormatter with exactMatch=false.
        // doesn't happen for DefaultJPQLQueryFormatter
    }

    /**
     * WhereClauseStateObject.andParse() doesn't preserve order of operations. I think it should?
     */
    @Test
    public void testAndParseOrderOfOperations() throws Exception {

        String jpql = "SELECT r FROM AnyRelationshipType r WHERE r.name = a OR r.name = b";
        JPQLQueryStateObject so = queryBuilder.buildStateObject(getPersistenceUnit(), jpql, false);

        SelectStatementStateObject selectSO = (SelectStatementStateObject) so.getQueryStatement();
        selectSO.getWhereClause().andParse("r.name = c OR r.name = d");

        IJPQLQueryFormatter formatter = new DefaultJPQLQueryFormatter(IdentifierStyle.UPPERCASE);
        assertEquals("SELECT r FROM AnyRelationshipType r WHERE (r.name = a OR r.name = b) AND (r.name = c OR r.name = d)", formatter.toString(so));

        // instead formatter.toString(so) returns:
        // SELECT r FROM AnyRelationshipType r WHERE r.name = a OR r.name = b
        // AND r.name = c OR r.name = d
        // which is logically different
    }

    /**
     * formatter throws StackOverflowError on "IS NULL"
     */
    @Test
    public void testFormatterIsNullOrderStackOverflow() throws Exception {
        String jpql = "SELECT r FROM AnyRelationshipType r WHERE r.groupUUID IS NULL";
        JPQLQueryStateObject so = queryBuilder.buildStateObject(getPersistenceUnit(), jpql, true);

        IJPQLQueryFormatter formatter = new DefaultActualJPQLQueryFormatter(false);
        assertEquals(jpql, formatter.toString(so)); // fails with
                                                    // StackOverflowError
    }

    /**
     * Default formatter still throws StackOverflowError on "IS NULL"
     */
    @Test
    public void testFormatterIsNullStackOverflow() throws Exception {
        String jpql = "SELECT r FROM AnyRelationshipType r WHERE r.groupUUID IS NULL";
        JPQLQueryStateObject so = queryBuilder.buildStateObject(getPersistenceUnit(), jpql, true);
        IJPQLQueryFormatter formatter = new DefaultActualJPQLQueryFormatter(false);
        assertEquals(jpql, formatter.toString(so)); // passes
        formatter = new DefaultJPQLQueryFormatter(IdentifierStyle.UPPERCASE);
        assertEquals(jpql, formatter.toString(so)); // fails with StackOverflowError
    }

    /**
     * DefaultJPQLQueryFormatter omits important space after LIKE
     */
    @Test
    public void testFormatterLikeMissingSpace() throws Exception  {
        String jpql = "SELECT a FROM Asset a WHERE a.name LIKE a.address";

        JPQLQueryStateObject so = queryBuilder.buildStateObject(getPersistenceUnit(), jpql, false);

        IJPQLQueryFormatter formatter = new DefaultJPQLQueryFormatter(IdentifierStyle.UPPERCASE);
        assertEquals(jpql, formatter.toString(so));
        // instead formatter.toString(so) returns:
        // SELECT a FROM Asset a WHERE a.name LIKEa.address'
    }

    /**
     * lowercase 'true" is formatted as NULL
     */
    @Test
    public void testFormatterLowercaseTrue() throws Exception  {

        String jpql = "SELECT a FROM Asset a WHERE a.good = TRUE";
        JPQLQueryStateObject so = queryBuilder.buildStateObject(getPersistenceUnit(), jpql, false);
        IJPQLQueryFormatter formatter = new DefaultActualJPQLQueryFormatter(true);
        assertEquals(jpql, formatter.toString(so)); // this works

        jpql = "SELECT a FROM Asset a WHERE a.good = true";
        so = queryBuilder.buildStateObject(getPersistenceUnit(), jpql, false);
        formatter = new DefaultActualJPQLQueryFormatter(true);
        assertEquals(jpql, formatter.toString(so));
        // instead formatter.toString(so) returns:
        // SELECT a FROM Asset a WHERE a.good = NULL
    }

    /**
     * Not causes StackOverflow
     */
    @Test
    public void testFormatterNot() throws Exception {
        String jpql = "SELECT a FROM Artifact a WHERE NOT (a.name = 'fred')";
        JPQLQueryStateObject so = queryBuilder.buildStateObject(getPersistenceUnit(), jpql, false);
        IJPQLQueryFormatter formatter = new DefaultActualJPQLQueryFormatter(true);
        assertEquals(jpql, formatter.toString(so));
        // fails with DefaultJPQLQueryFormatter too
    }

    /**
     * DefaultActualJPQLQueryFormatter with exactMatch=true omits important space before ORDER BY
     */
    @Test
    public void testFormatterOrderByMissingSpace() throws Exception  {
        String jpql = "SELECT a FROM Asset a WHERE a.good = TRUE ORDER BY a.size";

        JPQLQueryStateObject so = queryBuilder.buildStateObject(getPersistenceUnit(), jpql, false);

        IJPQLQueryFormatter formatter = new DefaultActualJPQLQueryFormatter(true);
        assertEquals(jpql, formatter.toString(so));
        // instead formatter.toString(so) returns: TRUEORDER BY a.size
    }

    /**
     * "IS EMPTY" is formatted as "null"
     */
    @Test
    public void testFormatterOrderStackOverflow() throws Exception  {
        String jpql = "SELECT r FROM AnyRelationshipType r WHERE r.groupUUID IS EMPTY";
        JPQLQueryStateObject so = queryBuilder.buildStateObject(getPersistenceUnit(), jpql, false);

        IJPQLQueryFormatter formatter = new DefaultActualJPQLQueryFormatter(false);
        assertEquals(jpql, formatter.toString(so));
        // instead formatter.toString(so) returns:
        // SELECT r FROM AnyRelationshipType r WHERE r.groupUUID null
    }
}
