/*
 * Copyright (c) 1998, 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
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.testing.tests.queries;

import java.util.*;

import org.eclipse.persistence.testing.framework.*;
import org.eclipse.persistence.testing.models.employee.domain.*;
import org.eclipse.persistence.queries.*;
import org.eclipse.persistence.expressions.*;
import org.eclipse.persistence.sessions.*;

/**
 * Runs cursored stream tests with conforming.
 * @bug 3009570 Conforming Cursors
 * @author Stephen McRitchie
 */

public class CursoredStreamConformingTest extends CursoredStreamTest
{
    protected ConformingTestConfiguration configuration;
    protected boolean useNestedUnitOfWork;

public CursoredStreamConformingTest() {
    super(Employee.class, (new ExpressionBuilder()).get("salary").greaterThan(50000));
    configuration = new ConformingTestConfiguration();
}

public CursoredStreamConformingTest(boolean useNestedUnitOfWork) {
    this();
    if (useNestedUnitOfWork) {
        setName(getName() + ":NestedUnitOfWork");
        this.useNestedUnitOfWork = true;
    }

}
protected void setup()
{
    getSession().getIdentityMapAccessor().initializeAllIdentityMaps();

    configuration.setup(getSession());
    UnitOfWork unitOfWork = configuration.getUnitOfWork();

    ReadAllQuery query = new ReadAllQuery(getReferenceClass(), joinExpression);
    query.conformResultsInUnitOfWork();
    Vector result = (Vector)unitOfWork.executeQuery(query);

    // Since conforming can not preserve order, must simply compare the
    // two results by PK.
    Vector expectedPKs = new Vector(result.size());
    for (Enumeration enumtr = result.elements(); enumtr.hasMoreElements();) {
        Employee emp = (Employee)enumtr.nextElement();
        expectedPKs.add(emp.getId());
    }
    setNormalQueryObjects(expectedPKs);

    configuration.reset();
    getSession().getIdentityMapAccessor().initializeAllIdentityMaps();

    configuration.setup(getSession());
    if (useNestedUnitOfWork) {
        getExecutor().setSession(configuration.getUnitOfWork().acquireUnitOfWork());
    } else {
        getExecutor().setSession(configuration.getUnitOfWork());
    }
}
public void test ( ) {

    ReadAllQuery query = new ReadAllQuery();
    CursoredStream stream = null;

    try {
        Object databaseObject;

        cursoredQueryObjects = new Vector();

        query.setReferenceClass(getReferenceClass());
        query.setSelectionCriteria(joinExpression);
        query.conformResultsInUnitOfWork();
        query.useCursoredStream();
        stream = (CursoredStream) getSession().executeQuery(query);

        // Test dual cursors and read(int)
        CursoredStream stream2 = (CursoredStream) getSession().executeQuery(query);
        try {
        stream2.read(5);
        } catch (org.eclipse.persistence.exceptions.QueryException ex) {} // ignore at end
        stream2.close();
        while (!stream.atEnd()) {
            databaseObject = stream.read();
            getCursoredQueryObjects().addElement(((Employee)databaseObject).getId());
            stream.releasePrevious();
        }
    } finally {
        if (stream != null) {
            stream.close();
        }
    }
}
/**
 * Verify if number of query objects matches number of cursor objects
 */
protected void verify()
{
    //System.out.println("Normal objects: " + getNormalQueryObjects());
    //System.out.println("Conforming objects: " + getCursoredQueryObjects());
    if (getNormalQueryObjects().size() != getCursoredQueryObjects().size()) {
        throw new TestErrorException("The number of streamed objects does not match the number of objects stored on the database ");
    }

    if (getNormalQueryObjects().size() == 0) {
        throw new TestWarningException("no object with the specified selection criteria was found ");
    }

    for (Enumeration enumtr = getNormalQueryObjects().elements(); enumtr.hasMoreElements();) {
        Object nextObject = enumtr.nextElement();
        if (!getCursoredQueryObjects().remove(nextObject)) {
            throw new TestErrorException("The following element was not found in the conformed result: " + nextObject);
        }
    }
}

public void reset() {
    if (useNestedUnitOfWork) {
        getExecutor().getSession().release();
    }
    getExecutor().setSession(configuration.getUnitOfWork().getParent());
    configuration.reset();
}
}
