/*
 * Copyright (c) 1998, 2020 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.transaction;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import jakarta.transaction.Synchronization;

import org.eclipse.persistence.exceptions.EclipseLinkException;
import org.eclipse.persistence.exceptions.TransactionException;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.internal.sequencing.SequencingCallback;
import org.eclipse.persistence.internal.sequencing.SequencingCallbackFactory;
import org.eclipse.persistence.logging.*;
import org.eclipse.persistence.sessions.broker.SessionBroker;
import org.eclipse.persistence.sessions.SessionProfiler;
import org.eclipse.persistence.sessions.DatabaseSession;

/**
 * <p>
 * <b>Purpose</b>: Abstract Synchronization Listener class
 *
 * <b>Description</b>: This abstract class is paired with the
 * AbstractTransactionController class. It contains most of the implementation
 * logic to handle callback notifications from an external transaction
 * manager to ensure consistency between the global transaction and the
 * EclipseLink unit of work. It does not assume any particular specification
 * or interface, but can be called by any implementation subclass.
 *
 * @see AbstractTransactionController
 */
public abstract class AbstractSynchronizationListener implements Synchronization {

    /**
     * The external txn controller that is intimate with the transaction manager
     * and knows how to do things like rolling back transactions, etc.
     */
    protected AbstractTransactionController controller;

    /**
     * The parent of the uow.
     */
    protected AbstractSession session;

    /**
     * The unit of work associated with the global txn that this listener is
     * bound to.
     * Note that unitOfWork is null in case it's a purely sequencing listener.
     */
    protected UnitOfWorkImpl unitOfWork;

    /**
     * The global transaction object.
     */
    protected Object transaction;

    /**
     * The global transaction key.
     */
    protected Object transactionKey;

    /**
     * sequencingCallback used in case listener has a single callback.
     */
    protected SequencingCallback sequencingCallback;

    /**
     * sequencingCallbackMap used in case listener has more than one callback:
     * SessionBroker with at least two members requiring callbacks.
     */
    protected Map<DatabaseSession, SequencingCallback> sequencingCallbackMap;

    /**
     * INTERNAL:
     */
    public AbstractSynchronizationListener() {
        super();
    }

    /**
     * INTERNAL:
     */
    protected AbstractSynchronizationListener(UnitOfWorkImpl unitOfWork, AbstractSession session, Object transaction, AbstractTransactionController controller) {
        this.session = session;
        this.unitOfWork = unitOfWork;
        this.transaction = transaction;
        this.controller = controller;
        this.transactionKey = controller.getTransactionKey(transaction);
    }

    /**
     * INTERNAL:
     * This method performs the logic that occurs at transaction
     * completion time. This includes issuing the SQL, etc.
     * This method executes within the transaction context of the caller of
     * transaction.commit(), or in the case of container-managed transactions,
     * in the context of the method for which the Container started the transaction.
     */
    @Override
    public void beforeCompletion() {
        UnitOfWorkImpl uow = getUnitOfWork();
        // it's a purely sequencing listener - nothing to do in beforeCompletion.
        if(unitOfWork == null) {
            return;
        }
        try {
            Object status = getTransactionController().getTransactionStatus();
            getTransactionController().logTxStateTrace(uow, "TX_beforeCompletion", status);
            //CR# 3452053
            session.startOperationProfile(SessionProfiler.JtsBeforeCompletion);

            // In case jts transaction was internally started but completed
            // directly by TransactionManager this flag is still set to true.
            getSession().setWasJTSTransactionInternallyStarted(false);

            // If the uow is not active then somebody somewhere messed up
            if (!uow.isActive()) {
                throw TransactionException.inactiveUnitOfWork(uow);
            }

            // Bail out if we don't think we should actually issue the SQL
            if (!getTransactionController().canIssueSQLToDatabase_impl(status)) {
                // Must force concurrency mgrs active thread if in nested transaction
                if (getSession().isInTransaction()) {
                    getSession().getTransactionMutex().setActiveThread(Thread.currentThread());
                    if(getUnitOfWork().wasTransactionBegunPrematurely()) {
                        getUnitOfWork().setWasTransactionBegunPrematurely(false);
                    }
                    getSession().rollbackTransaction();
                }
                getSession().releaseJTSConnection();
                return;
            }

            // Must force concurrency mgrs active thread if in nested transaction
            if (getSession().isInTransaction()) {
                getSession().getTransactionMutex().setActiveThread(Thread.currentThread());
            }

            // If sequencing callback for this transaction will be required
            // in case it doesn't already exist it will be created on this very listener
            // avoiding adding more listeners while processing a listener.
            if(getTransactionController().isSequencingCallbackRequired()) {
                getTransactionController().currentlyProcessedListeners.put(getTransactionKey(), this);
            }

            // Send the SQL to the DB
            uow.issueSQLbeforeCompletion();

            // Fix up our merge state in the unit of work and the session
            uow.setPendingMerge();

        } catch (RuntimeException exception) {
            // Log the exception if it has not already been logged, or is a non-EclipseLink exception
            if (!(exception instanceof EclipseLinkException && ((EclipseLinkException)exception).hasBeenLogged())) {
                uow.logThrowable(SessionLog.WARNING, SessionLog.TRANSACTION, exception);
            }

            // Handle the exception according to transaction manager requirements
            handleException(exception);
        } finally {
            if(getTransactionController().isSequencingCallbackRequired()) {
                getTransactionController().currentlyProcessedListeners.remove(getTransactionKey());
            }
            getSession().releaseJTSConnection();
            session.endOperationProfile(SessionProfiler.JtsBeforeCompletion);
        }
    }

    /**
     * INTERNAL:
     * The method performs the logic that should be executed after the transaction
     * has been completed. The status passed in indicates whether the transaction
     * was committed or rolled back. This status flag may be different for different
     * implementations.
     * This method executes without a transaction context.
     *
     * @param status The status code of the transaction completion.
     */
    public void afterCompletion(Object status) {
        UnitOfWorkImpl uow = getUnitOfWork();
        // it's a purely sequencing listener - call sequencing callback if the transaction has committed.
        if(uow == null) {
            if(getTransactionController().isSequencingCallbackRequired()) {
                if(getTransactionController().canMergeUnitOfWork_impl(status)) {
                    callSequencingCallback();
                }
            }
        } else {
            try {
                // Log the fact that we got invoked
                getTransactionController().logTxStateTrace(uow, "TX_afterCompletion", status);
                //Cr#3452053
                this.session.startOperationProfile(SessionProfiler.JtsAfterCompletion);
                // The uow should still be active even in rollback case
                if (!uow.isActive()) {
                    throw TransactionException.inactiveUnitOfWork(uow);
                }

                // Only do merge if txn was committed
                if (getTransactionController().canMergeUnitOfWork_impl(status)) {
                    if(getTransactionController().isSequencingCallbackRequired()) {
                        callSequencingCallback();
                    }
                    if (uow.isMergePending()) {
                        // uow in PENDING_MERGE state, merge clones
                        uow.mergeClonesAfterCompletion();
                    }
                } else {
                    // call this method again because there may have been no beforeCompletion call
                    // if case transaction is to be rolled back.
                    getSession().releaseJTSConnection();
                    uow.afterExternalTransactionRollback();
                }

                // Clean up by releasing the uow and client session
                if (uow.shouldResumeUnitOfWorkOnTransactionCompletion() && getTransactionController().canMergeUnitOfWork_impl(status)){
                    uow.synchronizeAndResume();
                    uow.setSynchronized(false);
                } else {
                    uow.release();
                    // Release the session explicitly
                    if (getSession().isClientSession() || (getSession().isSessionBroker() && ((SessionBroker)getSession()).isClientSessionBroker())) {
                        getSession().release();
                    }
                }
            } catch (RuntimeException exception) {
                // Log the exception if it has not already been logged, or is a non-EclipseLink exception
                if (!(exception instanceof EclipseLinkException && ((EclipseLinkException)exception).hasBeenLogged())) {
                    uow.logThrowable(SessionLog.WARNING, SessionLog.TRANSACTION, exception);
                }
                handleException(exception);
            } finally {
                getTransactionController().removeUnitOfWork(getTransactionKey());
                this.session.endOperationProfile(SessionProfiler.JtsAfterCompletion);
                setUnitOfWork(null);
                setSession(null);
            }
        }
        if(getTransactionController().isSequencingCallbackRequired()) {
            getTransactionController().removeSequencingListener(getTransactionKey());
            this.sequencingCallback = null;
            this.sequencingCallbackMap = null;
        }
        setTransaction(null);
        setTransactionKey(null);
    }

    /**
     * INTERNAL:
     * Do the appropriate thing for when an exception occurs during SQL issuance.
     * The default thing to do is to simply mark the transaction to be rolled back,
     * for those transaction managers that support this, and rethrow the exception.
     * We hope that the exception will do the trick for those that do not allow
     * marking rollback.
     *
     * This method may optionally be overridden by concrete subclass implementations.
     * Different transaction manager vendors may have different reactions to exceptions
     * that get signalled during the commit phase of synchronization.
     */
    public void handleException(RuntimeException exception) {
        // Don't do this just yet, since some may not be able to handle it
        //    getTransactionController().markTransactionForRollback();
        if (this.controller.getExceptionHandler() != null) {
            this.controller.getExceptionHandler().handleException(exception);
            return;
        }
        throw exception;
    }

    protected AbstractTransactionController getTransactionController() {
        return controller;
    }

    protected void setTransactionController(AbstractTransactionController newController) {
        controller = newController;
    }

    protected Object getTransaction() {
        return transaction;
    }

    protected void setTransaction(Object transaction) {
        this.transaction = transaction;
    }

    protected Object getTransactionKey() {
        return transactionKey;
    }

    protected void setTransactionKey(Object transactionKey) {
        this.transactionKey = transactionKey;
    }

    protected AbstractSession getSession() {
        return session;
    }

    protected void setSession(AbstractSession session) {
        this.session = session;
    }

    protected UnitOfWorkImpl getUnitOfWork() {
        return unitOfWork;
    }

    protected void setUnitOfWork(UnitOfWorkImpl unitOfWork) {
        this.unitOfWork = unitOfWork;
    }

    protected void callSequencingCallback() {
        if(sequencingCallback != null) {
            sequencingCallback.afterCommit(null);
        } else if (sequencingCallbackMap != null) {
            Iterator<SequencingCallback> itCallback = sequencingCallbackMap.values().iterator();
            while(itCallback.hasNext()) {
                itCallback.next().afterCommit(null);
            }
        }
    }

    /**
     * Return sequencingCallback corresponding to the passed session.
     */
    public SequencingCallback getSequencingCallback(DatabaseSession dbSession, SequencingCallbackFactory sequencingCallbackFactory) {
        if(getTransactionController().numSessionsRequiringSequencingCallback() == 1) {
            if(sequencingCallback == null) {
                sequencingCallback = sequencingCallbackFactory.createSequencingCallback();
            }
            return sequencingCallback;
        } else if(getTransactionController().numSessionsRequiringSequencingCallback() > 1) {
            SequencingCallback callback = null;
            if(sequencingCallbackMap == null) {
                sequencingCallbackMap = new HashMap(getTransactionController().numSessionsRequiringSequencingCallback());
            } else {
                callback = sequencingCallbackMap.get(dbSession);
            }
            if(callback == null) {
                callback = sequencingCallbackFactory.createSequencingCallback();
                sequencingCallbackMap.put(dbSession, callback);
            }
            return callback;
        } else {
            // should never happen.
            return null;
        }
    }
}
