/*
 * 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 java.util.*;
import org.eclipse.persistence.descriptors.*;
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.testing.models.employee.domain.*;
import org.eclipse.persistence.testing.framework.*;
import org.eclipse.persistence.exceptions.*;

/**
 * Tests fine-grained / descriptor level pessimistic locking with batch
 * attributes.
 * <p>
 * When a collection of objects are batch-read by one user, these objects
 * should not be accessable to any other user.
 */
public class PessimisticLockBatchAttributeTest extends TestCase {
    public UnitOfWork uow;
    public short lockMode;
    CMPPolicy oldCMPPolicy;

    public PessimisticLockBatchAttributeTest() {
        this.lockMode = ObjectLevelReadQuery.LOCK_NOWAIT;
        setDescription("Verfies that objects pessimistically locked by one user in a batch read are not accessable to others.");
    }

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

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

        ClassDescriptor employeeDescriptor = getSession().getDescriptor(Employee.class);
        ((ObjectLevelReadQuery)((ForeignReferenceMapping)employeeDescriptor.getMappingForAttributeName("phoneNumbers")).getSelectionQuery()).setLockMode(ObjectLevelReadQuery.DEFAULT_LOCK_MODE);

        ClassDescriptor phoneDescriptor = getSession().getDescriptor(PhoneNumber.class);
        oldCMPPolicy = phoneDescriptor.getCMPPolicy();
        phoneDescriptor.setCMPPolicy(cmpPolicy);
        phoneDescriptor.getQueryManager().getReadObjectQuery().setLockMode(ObjectLevelReadQuery.DEFAULT_LOCK_MODE);
    }

    @Override
    public void reset() {
        getSession().getIdentityMapAccessor().initializeAllIdentityMaps();
        if (uow != null) {
            uow.release();
        }
        ClassDescriptor employeeDescriptor = getSession().getDescriptor(Employee.class);
        ((ObjectLevelReadQuery)((ForeignReferenceMapping)employeeDescriptor.getMappingForAttributeName("phoneNumbers")).getSelectionQuery()).setLockMode(ObjectLevelReadQuery.DEFAULT_LOCK_MODE);
        ((ObjectLevelReadQuery)((ForeignReferenceMapping)employeeDescriptor.getMappingForAttributeName("phoneNumbers")).getSelectionQuery()).dontRefreshIdentityMapResult();

        ClassDescriptor phoneDescriptor = getSession().getDescriptor(PhoneNumber.class);
        phoneDescriptor.setCMPPolicy(oldCMPPolicy);
        phoneDescriptor.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();

        ReadAllQuery query = new ReadAllQuery(Employee.class);
        query.addBatchReadAttribute(query.getExpressionBuilder().get("phoneNumbers"));

        Vector result = (Vector)uow.executeQuery(query);

        // Now trigger the valueholders...  After this all phoneNumbers should be
        // locked by uow1.
        Vector phones = ((Employee)result.elementAt(0)).getPhoneNumbers();

        // Test the locks.
        // Because this is on a ServerSession the second UOW will have its own
        // ClientSession/exclusive connection.
        UnitOfWork uow2 = getSession().acquireUnitOfWork();
        try {
            boolean isLocked = false;
            ReadObjectQuery uow2Query = new ReadObjectQuery(Employee.class);
            Employee employee = (Employee)uow2.executeQuery(uow2Query);

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

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

            try {
                employee.getPhoneNumbers();
            } catch (EclipseLinkException exception) {
                throw new TestErrorException("Now that a batch attribute locked by UOW1 has been released it should be readable now.");
            }
        } catch (RuntimeException e) {
            throw e;
        } finally {
            if (uow2 != null) {
                uow2.release();
            }
        }
    }
}
