/*
 * 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
//     14/05/2012-2.4 Guy Pelletier
//       - 376603: Provide for table per tenant support for multitenant applications
package org.eclipse.persistence.testing.tests.unitofwork;

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

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.sessions.UnitOfWork;
import org.eclipse.persistence.testing.framework.TestErrorException;
import org.eclipse.persistence.testing.framework.TestWarningException;
import org.eclipse.persistence.testing.framework.TransactionalTestCase;
import org.eclipse.persistence.testing.models.insurance.PolicyHolder;


public class NoIdentityMergeCloneTest extends TransactionalTestCase {
    protected PolicyHolder objectToBeWritten;
    protected Hashtable checkCacheState;
    protected Hashtable identityMapTypes;

    public NoIdentityMergeCloneTest() {
        setDescription("Test that the unit of work mergeClone still works when object identity is lost.");
    }

    @Override
    public void reset() {
        if (getSession() instanceof org.eclipse.persistence.sessions.remote.RemoteSession) {
            return;
        }
        super.reset();
        Enumeration enumtr = checkCacheState.keys();
        while (enumtr.hasMoreElements()) {
            ClassDescriptor key = (ClassDescriptor)enumtr.nextElement();
            key.getQueryManager().getDoesExistQuery().setExistencePolicy((Integer) checkCacheState.get(key));
        }
        enumtr = identityMapTypes.keys();
        while (enumtr.hasMoreElements()) {
            ClassDescriptor key = (ClassDescriptor)enumtr.nextElement();
            key.setIdentityMapClass((Class)identityMapTypes.get(key));
        }
    }

    @Override
    public void setup() {
        if (getSession() instanceof org.eclipse.persistence.sessions.remote.RemoteSession) {
            throw new TestWarningException("Not support in remote");
        }
        super.setup();
        //Have to keep track of what the setting for existence checking and IM types on a per descriptor basis
        // because it may not be the same for all descriptors.
        this.checkCacheState = new Hashtable(10);
        this.identityMapTypes = new Hashtable(10);
        Iterator iterator = getSession().getProject().getDescriptors().values().iterator();
        while (iterator.hasNext()) {
            ClassDescriptor descriptor = (ClassDescriptor)iterator.next();
            checkCacheState.put(descriptor,
                    descriptor.getQueryManager().getDoesExistQuery().getExistencePolicy());
            if(descriptor.requiresInitialization((AbstractSession) getSession())) {
                // identityMapClass is null for AggregateObject, AggregateMapping and Interface descriptors.
                identityMapTypes.put(descriptor, descriptor.getIdentityMapClass());
            }
        }
        getSession().getProject().checkDatabaseForDoesExist();
        getSession().getProject().useCacheIdentityMap(1);
        getSession().getIdentityMapAccessor().initializeAllIdentityMaps();
    }

    @Override
    public void test() {
        this.objectToBeWritten =
                (PolicyHolder)(getSession().readAllObjects(org.eclipse.persistence.testing.models.insurance.PolicyHolder.class)).firstElement();
        this.objectToBeWritten =
                (PolicyHolder)getSession().acquireUnitOfWork().registerObject(this.objectToBeWritten);
        this.objectToBeWritten.setAddress(null);

        UnitOfWork uow = getSession().acquireUnitOfWork();
        uow.mergeClone(this.objectToBeWritten);
        uow.commit();
    }

    @Override
    public void verify() {
        getSession().getIdentityMapAccessor().initializeIdentityMaps();
        Object objectFromDatabase = getSession().readObject(this.objectToBeWritten);

        if (!(compareObjects(this.objectToBeWritten, objectFromDatabase))) {
            throw new TestErrorException("The object inserted into the database, '" + objectFromDatabase +
                                         "' does not match the original, '" + this.objectToBeWritten + ".");
        }
    }
}
