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

import org.eclipse.persistence.descriptors.*;
import org.eclipse.persistence.expressions.*;
import org.eclipse.persistence.mappings.*;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.queries.*;
import org.eclipse.persistence.sessions.*;
import org.eclipse.persistence.exceptions.*;

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

/**
 * Tests fine-grained / descriptor level pessimistic locking with joined
 * attributes.
 * <p>
 * Specifically tests the unusual cases of bug 3422202, and makes sure the
 * joined attributes are properly recorded with the correct session.
 * <p>
 * This test must be run using the ServerSessionTestAdaptor, so that each
 * UnitOfWork is on a separate UnitOfWork, each having their own transaction
 * but still sharing the global cache.
 * <p>
 * Test cases:
 * <ul>
 * <li>Query on a project, where team leader and its address are joined.  Query
 * for both the address and the employee: and check the SQL to see if had
 * a cache hit (or checkCacheOnly).
 * <li>Query on a project, where team leader is joined.  Then in a separate UnitOfWork
 * query on the same project where team leader is not joined, and then attempt
 * project.getTeamLeader().  This should fail.
 * <li>Query on a project, where team leader is not joined.  Then in a separate
 * UnitOfWork query on the project where team leader is joined.  Then try to
 * get the teamleader on the first UnitOfWork.  This should fail.
 * <li>Query on a project, where team leader is joined, and rollback.  Change
 * the cache copy and then have another read the project where team leader is
 * joined.  The query and the refresh should succeed.
 * </ul>
 */
public class PessimisticLockJoinedAttributeTest extends TestCase {
    public UnitOfWork uow;
    public short lockMode;
    CMPPolicy oldCMPPolicy;

    /**
     * PessimisticLockInheritanceTest constructor comment.
     */
    public PessimisticLockJoinedAttributeTest() {
        this.lockMode = ObjectLevelReadQuery.LOCK_NOWAIT;
        setDescription("For bug 3422202 verifies the pessimistic locking feature works properly when set on the descriptor and joined attributes are involved.");
    }

    @Override
    protected void setup() {
        getSession().getIdentityMapAccessor().initializeIdentityMaps();

        PessimisticLockingPolicy policy = new PessimisticLockingPolicy();
        policy.setLockingMode(this.lockMode);
        CMPPolicy cmpPolicy = new CMPPolicy();
        cmpPolicy.setPessimisticLockingPolicy(policy);

        ClassDescriptor projectDescriptor = getSession().getDescriptor(org.eclipse.persistence.testing.models.employee.domain.Project.class);
        ((ObjectLevelReadQuery)((ForeignReferenceMapping)projectDescriptor.getMappingForAttributeName("teamLeader")).getSelectionQuery()).setLockMode(ObjectLevelReadQuery.DEFAULT_LOCK_MODE);

        ClassDescriptor employeeDescriptor = getSession().getDescriptor(Employee.class);
        oldCMPPolicy = employeeDescriptor.getCMPPolicy();
        employeeDescriptor.setCMPPolicy(cmpPolicy);
        employeeDescriptor.getQueryManager().getReadObjectQuery().setLockMode(ObjectLevelReadQuery.DEFAULT_LOCK_MODE);
        ((ObjectLevelReadQuery)((ForeignReferenceMapping)employeeDescriptor.getMappingForAttributeName("address")).getSelectionQuery()).setLockMode(ObjectLevelReadQuery.DEFAULT_LOCK_MODE);

        ClassDescriptor addressDescriptor = getSession().getDescriptor(Address.class);
        addressDescriptor.setCMPPolicy(cmpPolicy);
        addressDescriptor.getQueryManager().getReadObjectQuery().setLockMode(ObjectLevelReadQuery.DEFAULT_LOCK_MODE);
    }

    @Override
    public void reset() {
        getSession().getIdentityMapAccessor().initializeAllIdentityMaps();
        if (uow != null) {
            uow.release();
        }
        ClassDescriptor projectDescriptor = getSession().getDescriptor(org.eclipse.persistence.testing.models.employee.domain.Project.class);
        ((ObjectLevelReadQuery)((ForeignReferenceMapping)projectDescriptor.getMappingForAttributeName("teamLeader")).getSelectionQuery()).setLockMode(ObjectLevelReadQuery.DEFAULT_LOCK_MODE);
        ((ObjectLevelReadQuery)((ForeignReferenceMapping)projectDescriptor.getMappingForAttributeName("teamLeader")).getSelectionQuery()).dontRefreshIdentityMapResult();
        ClassDescriptor employeeDescriptor = getSession().getDescriptor(Employee.class);
        employeeDescriptor.setCMPPolicy(oldCMPPolicy);
        employeeDescriptor.getQueryManager().getReadObjectQuery().setLockMode(ObjectLevelReadQuery.DEFAULT_LOCK_MODE);

        ((ObjectLevelReadQuery)((ForeignReferenceMapping)employeeDescriptor.getMappingForAttributeName("address")).getSelectionQuery()).setLockMode(ObjectLevelReadQuery.DEFAULT_LOCK_MODE);
        ((ObjectLevelReadQuery)((ForeignReferenceMapping)employeeDescriptor.getMappingForAttributeName("address")).getSelectionQuery()).dontRefreshIdentityMapResult();

        ClassDescriptor addressDescriptor = getSession().getDescriptor(Address.class);
        addressDescriptor.setCMPPolicy(oldCMPPolicy);
        addressDescriptor.getQueryManager().getReadObjectQuery().setLockMode(ObjectLevelReadQuery.DEFAULT_LOCK_MODE);
    }

    @Override
    public void test() throws Exception {
        if (!getSession().getPlatform().isOracle() && !getSession().getPlatform().isSQLServer()) {
            throw new TestWarningException("This test only runs on Oracle wears writes do not block reads.");
        }

        uow = getSession().acquireUnitOfWork();

        ReadObjectQuery query = new ReadObjectQuery(LargeProject.class);

        // Only Charles Chanley and John Way are team leaders of projects they are also working on.
        Expression expression = query.getExpressionBuilder().get("teamLeader").get("firstName").equal("Charles");
        query.setSelectionCriteria(expression);
        query.addJoinedAttribute(query.getExpressionBuilder().get("teamLeader"));
        query.addJoinedAttribute(query.getExpressionBuilder().get("teamLeader").get("address"));

        Object result = uow.executeQuery(query);

        // Now trigger the valueholders...  These clones should be registered in
        // the uow and marked as already locked.
        // Check the SQL so that none gets issued.
        Employee charles = (Employee)((LargeProject)result).getTeamLeader();
        Address address = charles.getAddress();

        ReadObjectQuery cacheQuery = null;
        Object cachedObject = null;

        // There is only one address in the cache, and it will only be returned
        // if it was tracked as being locked.
        cacheQuery = new ReadObjectQuery(Address.class);
        cacheQuery.checkCacheThenDatabase();
        cachedObject = uow.executeQuery(cacheQuery);
        if (address != cachedObject) {
            throw new TestErrorException("Did not get a cache hit after pessimistically locking a nested joined attribute.");
        }
        cacheQuery = new ReadObjectQuery(org.eclipse.persistence.testing.models.employee.domain.Employee.class);
        cacheQuery.checkCacheThenDatabase();
        cachedObject = uow.executeQuery(cacheQuery);
        if (charles != cachedObject) {
            throw new TestErrorException("Did not get a cache hit after pessimisticly locking a joined attribute.");
        }

        // Test the lock.
        // Because this is on a ServerSession the second UOW will have its own
        // ClientSession/exclusive connection.
        UnitOfWork uow2 = getSession().acquireUnitOfWork();
        try {
            boolean isLocked = false;
            query = new ReadObjectQuery(LargeProject.class);
            expression = query.getExpressionBuilder().get("teamLeader").get("firstName").equal("Charles");
            query.setSelectionCriteria(expression);
            LargeProject result2 = (LargeProject)uow2.executeQuery(query);

            // assert(result2 != null, "It was never meant to be locked.");
            try {
                result2.getTeamLeader();
            } catch (EclipseLinkException exception) {
                isLocked = true;
            }
            if (!isLocked) {
                throw new TestErrorException("Triggering an attribute that was locked by another in a joined read should trigger a no_wait exception.");
            }

            // Now release the first UnitOfWork and try again.
            Employee originalCharles = (Employee)uow.getOriginalVersionOfObject(charles);
            uow.release();
            uow = null;

            // Now change the session copy, this is what would happen if the
            // object was actually committed to the database.  Want to test that
            // the object is refreshed when locked.
            originalCharles.setSalary(0);
            try {
                charles = (Employee)result2.getTeamLeader();
                address = charles.getAddress();
            } catch (EclipseLinkException exception) {
                throw new TestErrorException("Now that a joined attribute locked by UOW1 has been released it should be readable now.");
            }
            if (charles.getSalary() == 0) {
                throw new TestErrorException("When a joined attribute is locked by another after it is released, should get refreshed.");
            }
        } catch (RuntimeException e) {
            throw e;
        } finally {
            if (uow2 != null) {
                uow2.release();
            }
        }
    }
}
