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

import java.util.Enumeration;
import java.util.Hashtable;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.ReadObjectQuery;
import org.eclipse.persistence.sessions.UnitOfWork;
import org.eclipse.persistence.testing.tests.distributedservers.DistributedServer;
import org.eclipse.persistence.testing.tests.distributedservers.DistributedServersModel;
import org.eclipse.persistence.testing.framework.TestErrorException;
import org.eclipse.persistence.testing.models.employee.domain.Address;
import org.eclipse.persistence.testing.models.employee.domain.Employee;

/**
 * Tests fix for bug:3604593
 * This test checks to see that when changing an object's reference that
 * removing a referenced object in the database will not cause a corruption
 * when the original changeset containing the reference change gets propogated.
 */
public class InvalidateObjectWithMissingReferenceTest extends ConfigurableCacheSyncDistributedTest {
    ReadObjectQuery query;
    Employee originalObject;
    Address originalAddress;
    Address newAddress;
    DistributedServer server;

    public InvalidateObjectWithMissingReferenceTest() {
        super();
        setName("InvalidateObjectWithMissingReferenceTest");
        cacheSyncConfigValues.put(Employee.class, ClassDescriptor.SEND_OBJECT_CHANGES);
        cacheSyncConfigValues.put(Address.class, ClassDescriptor.DO_NOT_SEND_CHANGES);
    }

    @Override
    public void reset() {
        getSession().getIdentityMapAccessor().initializeAllIdentityMaps();
        Enumeration enumtr = DistributedServersModel.getDistributedServers().elements();
        while (enumtr.hasMoreElements()) {
            (((DistributedServer)enumtr.nextElement()).getDistributedSession()).getIdentityMapAccessor().initializeAllIdentityMaps();
        }
        Enumeration keys = oldCacheSyncConfigValues.keys();
        while (keys.hasMoreElements()) {
            Class keyClass = (Class)keys.nextElement();
            ClassDescriptor descriptor = getSession().getDescriptor(keyClass);
            int newCacheSyncType = (Integer) oldCacheSyncConfigValues.get(keyClass);
            descriptor.setCacheSynchronizationType(newCacheSyncType);
        }
    }

    @Override
    public void setup() {
        oldCacheSyncConfigValues = new Hashtable();
        Enumeration keys = cacheSyncConfigValues.keys();
        while (keys.hasMoreElements()) {
            Class keyClass = (Class)keys.nextElement();
            ClassDescriptor descriptor = getSession().getDescriptor(keyClass);

            if (descriptor != null) {
                int cacheSyncType = descriptor.getCacheSynchronizationType();
                Object newCacheSyncType = cacheSyncConfigValues.get(keyClass);
                if (newCacheSyncType != null) {
                    oldCacheSyncConfigValues.put(keyClass, cacheSyncType);
                    descriptor.setCacheSynchronizationType((Integer) newCacheSyncType);
                }
            }
        }
        getSession().getIdentityMapAccessor().initializeAllIdentityMaps();

        this.originalObject = (Employee)getSession().readObject(Employee.class);
        this.originalAddress = this.originalObject.getAddress();
        this.query = new ReadObjectQuery();
        this.query.setSelectionObject(this.originalObject);
        this.server = (DistributedServer)DistributedServersModel.getDistributedServers().get(0);
        getEmployeeFromDistributedSession(this.query);
    }


    @Override
    protected void test() {

        UnitOfWork uow = getSession().acquireUnitOfWork();

        Employee empClone = (Employee)uow.registerObject(this.originalObject);

        this.newAddress = new Address();
        this.newAddress.setCity("Ottawa");
        this.newAddress.setPostalCode("K5J2B5");
        this.newAddress.setProvince("ONT");
        this.newAddress.setStreet("should not exist when test completes");
        this.newAddress.setCountry("Canada");
        Address addressClone = (Address)uow.registerObject(this.newAddress);
        empClone.setAddress(addressClone);
        uow.assignSequenceNumber(addressClone);
        //uow.commit() is broken into components to allow DB change before cache synch propogates changes
        ((UnitOfWorkImpl)uow).issueSQLbeforeCompletion();
        getAbstractSession().insertObject(this.originalAddress);

        getAbstractSession().getSessionForClass(Employee.class).executeNonSelectingSQL("UPDATE EMPLOYEE SET ADDR_ID = " + this.originalAddress.getId() + " WHERE (EMP_ID = " + empClone.getId() + ")");

        getAbstractSession().deleteObject(addressClone);

        ((UnitOfWorkImpl)uow).mergeClonesAfterCompletion();
    }


    @Override
    protected void verify() {
        Employee remoteEmployee = (Employee)getObjectFromDistributedCache(this.originalObject);
        if ((remoteEmployee != null) && (remoteEmployee.getAddress() == null)) {
            throw new TestErrorException("Employee's Address reference was corrupted during RCM synch" + " when Address was removed from the database. ");
        }
        remoteEmployee = getEmployeeFromDistributedSession(this.query);
        if (remoteEmployee.getAddress() == null) {
            throw new TestErrorException("Employee's Address reference was corrupted during RCM synch" + " when Address was removed from the database. ");
        }
        if (remoteEmployee.getAddress().getId() == newAddress.getId()) {
            throw new TestErrorException("New object Address was built/sent with the changeset in RCM " + "though its descriptor specifies DO_NOT_SEND_CHANGES");
        }

    }


    public Employee getEmployeeFromDistributedSession(DatabaseQuery query) {
        try {
            Employee result = (Employee)this.server.getDistributedSession().executeQuery(query);
            result.getAddress();
            return result;
        } catch (Exception exception) {
            return null;
        }
    }


}
