/*
 * Copyright (c) 1998, 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 from Oracle TopLink
package org.eclipse.persistence.testing.tests.queries.optimization;

import java.util.Vector;

import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;
import org.eclipse.persistence.sessions.UnitOfWork;
import org.eclipse.persistence.testing.models.mapping.Employee;
import org.eclipse.persistence.testing.framework.TestCase;
import org.eclipse.persistence.annotations.BatchFetchType;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.queries.ReadAllQuery;
import org.eclipse.persistence.queries.ReadObjectQuery;

// bug 6690525: STACKOVERFLOWERROR UNDER READALLQUERY.EXECUTE
public class BatchReadingStackOverflowTest extends TestCase {
    String firstName = "StackOverflowTest";
    Employee emp_1;
    ForeignReferenceMapping mappingToDisableBatchReadInReset;
    BatchFetchType batchType;

    public BatchReadingStackOverflowTest(BatchFetchType batchType) {
        this.batchType = batchType;
        setName(getName() + batchType);
    }

    @Override
    protected void setup() throws Throwable {
        if ((batchType == BatchFetchType.IN) && !getSession().getPlatform().isOracle()) {
            throwWarning("Nested arrays not supported on this database");
        }
        // set readBatch to true on managedEmployees mapping
        mappingToDisableBatchReadInReset = (ForeignReferenceMapping)getSession().getDescriptor(Employee.class).getMappingForAttributeName("managedEmployees");
        if(mappingToDisableBatchReadInReset.shouldUseBatchReading()) {
            // nothing to do - it already uses batch reading
            mappingToDisableBatchReadInReset = null;
        } else {
            mappingToDisableBatchReadInReset.setUsesBatchReading(true);
            mappingToDisableBatchReadInReset.setBatchFetchType(batchType);
            mappingToDisableBatchReadInReset.getSelectionQuery().setIsPrepared(false);
            ((ReadAllQuery)mappingToDisableBatchReadInReset.getSelectionQuery()).setBatchFetchPolicy(null);
            mappingToDisableBatchReadInReset.getDescriptor().getObjectBuilder().initializeBatchFetchedAttributes();
        }

        // create objects to be used by the test:
        // emp_1 has two managed employees, each of them has one managed employee.
        emp_1 = new Employee();
        emp_1.firstName = firstName;
        emp_1.lastName = "1";
        emp_1.sex = "male";
        emp_1.managedEmployees = new Vector(2);

        Employee emp_1_1 = new Employee();
        emp_1_1.firstName = firstName;
        emp_1_1.lastName = "1_1";
        emp_1_1.sex = "male";
        emp_1_1.managedEmployees = new Vector(1);
        emp_1.managedEmployees.add(emp_1_1);
        emp_1_1.manager = emp_1;

        Employee emp_1_2 = new Employee();
        emp_1_2.firstName = firstName;
        emp_1_2.lastName = "1_2";
        emp_1_2.sex = "male";
        emp_1_2.managedEmployees = new Vector(1);
        emp_1.managedEmployees.add(emp_1_2);
        emp_1_2.manager = emp_1;

        Employee emp_1_1_1 = new Employee();
        emp_1_1_1.firstName = firstName;
        emp_1_1_1.lastName = "1_1_1";
        emp_1_1_1.sex = "male";
        emp_1_1.managedEmployees.add(emp_1_1_1);
        emp_1_1_1.manager = emp_1_1;

        Employee emp_1_2_1 = new Employee();
        emp_1_2_1.firstName = firstName;
        emp_1_2_1.lastName = "1_2_1";
        emp_1_2_1.sex = "male";
        emp_1_2.managedEmployees.add(emp_1_2_1);
        emp_1_2_1.manager = emp_1_2;

        // Begin transaction here and rollback it in reset.
        ((AbstractSession)getSession()).beginTransaction();

        // write the objects into the db, merge them into session's cache.
        UnitOfWork uow = getSession().acquireUnitOfWork();
        uow.registerObject(emp_1);
        uow.commit();

        // now invalidate all the created objects in the session's cache
        getSession().getIdentityMapAccessor().invalidateObject(emp_1);
        getSession().getIdentityMapAccessor().invalidateObject(emp_1_1);
        getSession().getIdentityMapAccessor().invalidateObject(emp_1_2);
        getSession().getIdentityMapAccessor().invalidateObject(emp_1_1_1);
        getSession().getIdentityMapAccessor().invalidateObject(emp_1_2_1);

    }

    @Override
    protected void test() throws Throwable {
        // query to read emp_1
        ReadObjectQuery query = new ReadObjectQuery(Employee.class);
        ExpressionBuilder builder = query.getExpressionBuilder();
        Expression exp = builder.get("firstName").equal(firstName).and(builder.get("lastName").equal("1"));
        query.setSelectionCriteria(exp);
        // executing the query used to cause StackOverflow
        Employee empRead = (Employee)getSession().executeQuery(query);
        // the following line is provided just in case you need to put a break point after query execution
        empRead.getManagedEmployees().size();
        query = null;
    }

    @Override
    public void reset() throws Throwable {
        if(((AbstractSession)getSession()).isInTransaction()) {
            ((AbstractSession)getSession()).rollbackTransaction();
            getSession().getIdentityMapAccessor().initializeAllIdentityMaps();
        }

        if(mappingToDisableBatchReadInReset != null) {
            mappingToDisableBatchReadInReset.setUsesBatchReading(false);
            mappingToDisableBatchReadInReset.getSelectionQuery().setIsPrepared(false);
            ((ReadAllQuery)mappingToDisableBatchReadInReset.getSelectionQuery()).setBatchFetchPolicy(null);
            mappingToDisableBatchReadInReset.getDescriptor().getObjectBuilder().initializeBatchFetchedAttributes();
            mappingToDisableBatchReadInReset = null;
        }
    }
}
