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

import java.util.Vector;

import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.queries.ReadObjectQuery;
import org.eclipse.persistence.sessions.remote.RemoteSession;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.sessions.SessionEventListener;
import org.eclipse.persistence.sessions.UnitOfWork;
import org.eclipse.persistence.testing.tests.remote.RemoteModel;
import org.eclipse.persistence.testing.framework.AutoVerifyTestCase;
import org.eclipse.persistence.testing.framework.TestErrorException;
import org.eclipse.persistence.testing.framework.TestWarningException;
import org.eclipse.persistence.testing.models.employee.domain.Address;
import org.eclipse.persistence.testing.models.employee.domain.Employee;
import org.eclipse.persistence.testing.models.employee.domain.EmploymentPeriod;
import org.eclipse.persistence.testing.models.employee.domain.LargeProject;
import org.eclipse.persistence.testing.models.employee.domain.SmallProject;


public class ComplexMultipleUnitOfWorkTest extends AutoVerifyTestCase {
    public Employee readInSession;
    public Employee readInUow;
    public Employee newEmployeeInUow;
    public Employee readInFirstNestedUow;
    public UnitOfWork firstUnitOfWork;
    public UnitOfWork secondUnitOfWork;
    public UnitOfWork thirdUnitOfWork;
    // On some platforms (Sybase/Derby) if conn1 updates a row but hasn't yet committed transaction then
    // reading the row through conn2 may hang.
    // To avoid this problem the listener would decrement transaction isolation level,
    // then reading through conn2 no longer hangs, however may result (results on Sybase)
    // in reading of uncommitted data.
    SessionEventListener listener;

    /**
     * MultipleUnitOfWorkTestCase constructor comment.
     */
    public ComplexMultipleUnitOfWorkTest() {
        super();
    }

    public Address addressExample1() {
        Address address = new org.eclipse.persistence.testing.models.employee.domain.Address();

        address.setCity("Toronto");
        address.setPostalCode("L5J2B5");
        address.setProvince("ONT");
        address.setStreet("1450 Acme Cr., suite 4");
        address.setCountry("Canada");
        return address;
    }

    public Address addressExample2() {
        Address address = new org.eclipse.persistence.testing.models.employee.domain.Address();

        address.setCity("Ottawa");
        address.setPostalCode("K5J2B5");
        address.setProvince("ONT");
        address.setStreet("1450 Acme Cr., suite 4");
        address.setCountry("Canada");
        return address;
    }

    public Address addressExample3() {
        Address address = new org.eclipse.persistence.testing.models.employee.domain.Address();

        address.setCity("Sudbury");
        address.setPostalCode("L5J2B5");
        address.setProvince("ONT");
        address.setStreet("1450 Acme Cr., suite 4");
        address.setCountry("Canada");
        return address;
    }

    public Address addressExample4() {
        Address address = new org.eclipse.persistence.testing.models.employee.domain.Address();

        address.setCity("Niagra");
        address.setPostalCode("L5J2B5");
        address.setProvince("ONT");
        address.setStreet("1450 Acme Cr., suite 4");
        address.setCountry("Canada");
        return address;
    }

    protected void changeObject(Employee employee, UnitOfWork unitOfWork) {
        // Transformation
        employee.setNormalHours(new java.sql.Time[2]);
        employee.setStartTime(Helper.timeFromHourMinuteSecond(1, 1, 1));
        employee.setEndTime(Helper.timeFromHourMinuteSecond(1, 1, 1));
        // Aggregate
        employee.setPeriod(new EmploymentPeriod(Helper.dateFromYearMonthDate(1901, 1, 1),
                                                Helper.dateFromYearMonthDate(1902, 2, 2)));
        // One to many private
        employee.setPhoneNumbers(new Vector());
        employee.addPhoneNumber(new org.eclipse.persistence.testing.models.employee.domain.PhoneNumber("home", "613",
                                                                                              "2263374"));
        employee.addPhoneNumber(new org.eclipse.persistence.testing.models.employee.domain.PhoneNumber("office", "416",
                                                                                              "8224599"));
        // Many to many
        employee.setProjects(new Vector());
        employee.addProject((org.eclipse.persistence.testing.models.employee.domain.Project)unitOfWork.readObject(SmallProject.class));
        employee.addProject((org.eclipse.persistence.testing.models.employee.domain.Project)unitOfWork.readObject(LargeProject.class));
        // Direct collection
        employee.setResponsibilitiesList(new Vector());
        employee.addResponsibility("make coffee");
        employee.addResponsibility("buy donuts");
        // One to one private/public
        employee.setAddress(addressExample4());

        ((Employee)unitOfWork.readObject(Employee.class, new ExpressionBuilder().get("firstName").equal("Marcus"))).addManagedEmployee(employee);
    }

    public Employee createNewEmployeeObject() {
        Employee employee = new org.eclipse.persistence.testing.models.employee.domain.Employee();

        employee.setFirstName("Judy");
        employee.setLastName("Barney");
        employee.setMale();
        employee.setSalary(35000);
        employee.setPeriod(employmentPeriodExample());
        employee.setAddress(addressExample1());
        employee.addResponsibility("Make the coffee.");
        employee.addResponsibility("Clean the kitchen.");
        employee.addPhoneNumber(new org.eclipse.persistence.testing.models.employee.domain.PhoneNumber("Work", "613",
                                                                                              "2258812"));

        employee.addProject(smallProjectExample());

        return employee;
    }

    public EmploymentPeriod employmentPeriodExample() {
        EmploymentPeriod employmentPeriod = new org.eclipse.persistence.testing.models.employee.domain.EmploymentPeriod();

        employmentPeriod.setEndDate(org.eclipse.persistence.internal.helper.Helper.dateFromYearMonthDate(1996, 0, 1));
        employmentPeriod.setStartDate(org.eclipse.persistence.internal.helper.Helper.dateFromYearMonthDate(1993, 0, 1));
        return employmentPeriod;
    }

    public void processFirstUnitOfWork() throws Exception {
        Expression firstNameExpression;

        // Read the object in the session
        firstNameExpression = new ExpressionBuilder().get("firstName").equal("Bob");
        this.readInSession = (Employee)getSession().readObject(Employee.class, firstNameExpression);

        // Acquire unit of work
        // Read first object in the uow
        this.firstUnitOfWork = getSession().acquireUnitOfWork();
        firstNameExpression = new ExpressionBuilder().get("firstName").equal("John");
        this.readInUow = (Employee)this.firstUnitOfWork.readObject(Employee.class, firstNameExpression);

        Employee regDel = (Employee)this.firstUnitOfWork.registerObject(this.readInSession);
        // Must remove references to deleted objects.
        if (regDel.getManager() != null) {
            regDel.getManager().removeManagedEmployee(regDel);
        }
        for (java.util.Enumeration mgdEnum = regDel.getManagedEmployees().elements(); mgdEnum.hasMoreElements();
        ) {
            ((Employee)mgdEnum.nextElement()).setManager(null);
        }
        for (java.util.Enumeration mgdProjEnum =
             (this.firstUnitOfWork.readAllObjects(org.eclipse.persistence.testing.models.employee.domain.Project.class)).elements();
             mgdProjEnum.hasMoreElements(); ) {
            ((org.eclipse.persistence.testing.models.employee.domain.Project)mgdProjEnum.nextElement()).setTeamLeader(null);
        }

        // Delete the object read in the session    without registration.
        this.firstUnitOfWork.deleteObject(this.readInSession);

        // Create object in uow and register it.
        this.newEmployeeInUow = createNewEmployeeObject();
        Employee newEmployeeInFirstUow = (Employee)this.firstUnitOfWork.registerObject(this.newEmployeeInUow);

        // Must remove references to deleted objects.
        if (this.readInUow.getManager() != null) {
            this.readInUow.getManager().removeManagedEmployee(this.readInUow);
        }
        for (java.util.Enumeration mgdEnum = this.readInUow.getManagedEmployees().elements();
             mgdEnum.hasMoreElements(); ) {
            ((Employee)mgdEnum.nextElement()).setManager(null);
        }

        // Acquire first nested unit of work
        // Delete read object in the unit of work without registering it.
        // Read some object and change it.
        UnitOfWork firstNestedUow = this.firstUnitOfWork.acquireUnitOfWork();
        firstNestedUow.deleteObject(this.readInUow);

        Employee workingCopyOfNewEmployeeInSecondNestedUow =
            (Employee)firstNestedUow.registerObject(newEmployeeInFirstUow);

        workingCopyOfNewEmployeeInSecondNestedUow.setAddress(addressExample2());

        firstNestedUow.commit();

        // Acquire second nested     unit of work
        // Change the new object created in the parent.
        UnitOfWork secondNestedUow = this.firstUnitOfWork.acquireUnitOfWork();

        firstNameExpression = new ExpressionBuilder().get("firstName").equal("Marcus");
        this.readInFirstNestedUow = (Employee)secondNestedUow.readObject(Employee.class, firstNameExpression);
        this.readInFirstNestedUow.setAddress(addressExample3());

        secondNestedUow.commit();
        // Assign correct clone from root unit of work so compare verifies works correctly.
        this.readInFirstNestedUow = (Employee)secondNestedUow.getOriginalVersionOfObject(readInFirstNestedUow);
        this.firstUnitOfWork.commit();
    }

    public void processSecondUnitOfWork() {
        this.secondUnitOfWork = getSession().acquireUnitOfWork();

        ReadObjectQuery query = new ReadObjectQuery();
        query.setSelectionObject(this.newEmployeeInUow);

        Employee objectFromDatabase = (Employee)secondUnitOfWork.executeQuery(query);

        if (!(((AbstractSession)getSession()).compareObjects(this.newEmployeeInUow, objectFromDatabase))) {
            throw new TestErrorException("The object read from the database, '" + this.newEmployeeInUow +
                                         "' does not match the originial, '" + objectFromDatabase + ".");
        }

        query = new ReadObjectQuery();
        query.setSelectionObject(this.readInFirstNestedUow);

        objectFromDatabase = (Employee)secondUnitOfWork.executeQuery(query);

        if (!(((AbstractSession)getSession()).compareObjects(this.readInFirstNestedUow, objectFromDatabase))) {
            throw new TestErrorException("The object read from the database, '" + this.readInFirstNestedUow +
                                         "' does not match the originial, '" + objectFromDatabase + ".");
        }

        Employee workingCopy = (Employee)secondUnitOfWork.registerObject(this.newEmployeeInUow);
        changeObject(workingCopy, this.secondUnitOfWork);
        secondUnitOfWork.release();

        // Use the original session for comparision
        if (!((AbstractSession)getSession()).compareObjectsDontMatch(this.newEmployeeInUow, workingCopy)) {
            throw new TestErrorException("The original object was changed through changing the clone.");
        }
    }

    public void processThirdUnitOfWork() {
        this.thirdUnitOfWork = getSession().acquireUnitOfWork();

        Employee workingCopy = (Employee)thirdUnitOfWork.registerObject(this.newEmployeeInUow);
        changeObject(workingCopy, this.thirdUnitOfWork);

        if (!((AbstractSession)getSession()).compareObjectsDontMatch(this.newEmployeeInUow, workingCopy)) {
            throw new TestErrorException("The original object was changed through changing the clone.");
        }

        this.thirdUnitOfWork.commit();
    }

    @Override
    public void reset() {
        if(getAbstractSession().isInTransaction()) {
            getAbstractSession().rollbackTransaction();
        }
        getSession().getIdentityMapAccessor().initializeAllIdentityMaps();
        if(listener != null) {
            getAbstractSession().getParent().getEventManager().removeListener(listener);
            listener = null;
        }
    }

    @Override
    public void setup() {
        if (getSession().isClientSession()) {
            listener = checkTransactionIsolation();
        }
        if (getSession().isRemoteSession() && getSession().getDatasourcePlatform().isDerby()) {
            throw new TestWarningException("This test uses functionality that does not work over remote sessions in Apache Derby.");
        }
        getAbstractSession().beginTransaction();
    }

    public SmallProject smallProjectExample() {
        SmallProject smallProject = new SmallProject();

        smallProject.setName("Enterprise");
        smallProject.setDescription("A enterprise wide application using Visual J++ to report on the corporations Sybase and DB/2 database through TopLink.");
        return smallProject;
    }

    @Override
    public void test() throws Exception {
        processFirstUnitOfWork();
        processSecondUnitOfWork();
        processThirdUnitOfWork();
    }

    @Override
    public void verify() {
        getSession().getIdentityMapAccessor().initializeIdentityMaps();
        Session sessionToVerifyDelete;

        if (getSession() instanceof RemoteSession) {
            sessionToVerifyDelete = RemoteModel.getServerSession();
        } else {
            sessionToVerifyDelete = getSession();
        }
        // Verify if object deleted in the uow was deleted
        if (!(((AbstractSession)sessionToVerifyDelete).verifyDelete(this.readInSession))) {
            throw new TestErrorException("The object '" + this.readInSession +
                                         "'deleted in the uow was not completely deleted from the database.");
        }

        // Verify if object deleted in the uow was deleted
        if (!(((AbstractSession)sessionToVerifyDelete).verifyDelete(this.readInUow))) {
            throw new TestErrorException("The object '" + this.readInUow +
                                         "'deleted in the nested uow was not completely deleted from the database.");
        }

        ReadObjectQuery query = new ReadObjectQuery();
        query.setSelectionObject(this.newEmployeeInUow);

        Employee objectFromDatabase = (Employee)getSession().executeQuery(query);

        if (!(((AbstractSession)getSession()).compareObjects(this.newEmployeeInUow, objectFromDatabase))) {
            throw new TestErrorException("The object read from the database, '" + this.newEmployeeInUow +
                                         "' does not match the originial, '" + objectFromDatabase + ".");
        }
    }
}
