/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2021 IBM Corporation. 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.sessions;

import java.util.*;
import java.io.*;
import org.eclipse.persistence.queries.*;
import org.eclipse.persistence.core.sessions.CoreSessionEventManager;
import org.eclipse.persistence.internal.databaseaccess.*;
import org.eclipse.persistence.internal.sessions.*;
import org.eclipse.persistence.sessions.broker.SessionBroker;
import org.eclipse.persistence.sessions.server.ClientSession;
import org.eclipse.persistence.sessions.SessionProfiler;

/**
 * <p><b>Purpose</b>: Used to support session events.
 * To register for events notification an event listener must be registered with the session.
 *
 * @see Session#getEventManager()
 * @see SessionEvent
 */
public class SessionEventManager extends CoreSessionEventManager<SessionEventListener> implements Cloneable, Serializable {
    protected List<SessionEventListener> listeners;
    protected Session session;

    /**
     * INTERNAL:
     * Default constructor.
     */
    public SessionEventManager() {
        this.listeners = new ArrayList<>();
    }

    /**
     * PUBLIC:
     * Create a new session event manager for a session
     */
    public SessionEventManager(Session session) {
        this.listeners = new ArrayList<>();
        this.session = session;
    }

    /**
     * PUBLIC:
     * Add the event listener to the session.
     * The listener will receive all events raised by this session.
     * Also unit of works acquire from this session will inherit the listeners.
     * If session is a broker then its members add the listener, too.
     */
    @Override
    public void addListener(SessionEventListener listener) {
        if (this.session != null) {
            if (this.session.isConnected()) {
                synchronized(this) {
                    if (this.listeners != null) {
                        ArrayList<SessionEventListener> listenersCopy = new ArrayList(listeners);
                        listenersCopy.add(listener);
                        this.listeners = listenersCopy;
                    } else {
                        this.listeners = new ArrayList();
                        this.listeners.add(listener);
                    }
                }
            } else {
                getListeners().add(listener);
            }
            if (this.session.isSessionBroker()) {
                // add listener to member sessions
                Iterator<AbstractSession> memberSessions = ((SessionBroker)this.session).getSessionsByName().values().iterator();
                while (memberSessions.hasNext()) {
                    AbstractSession memberSession = memberSessions.next();
                    memberSession.getEventManager().addListener(listener);
                }
            }
        } else {
            getListeners().add(listener);
        }
    }

    /**
     * INTERNAL:
     * Shallow clone the event manager.
     */
    @Override
    public Object clone() {
        try {
            return super.clone();
        } catch (CloneNotSupportedException exception) {
            return new InternalError(exception.toString());
        }
    }

    /**
     * INTERNAL:
     * Clone the event manager for the new session.
     */
    public SessionEventManager clone(Session newSession) {
        SessionEventManager newManager = (SessionEventManager)clone();
        newManager.setSession(newSession);
        if (this.listeners != null) {
            newManager.setListeners(new ArrayList<>(this.listeners));
        }
        return newManager;
    }

    /**
     * PUBLIC:
     * The event listeners will receive all events raised by this session.
     * Also unit of works acquire from this session will inherit the listeners.
     */
    public List<SessionEventListener> getListeners() {
        if (listeners == null) {
            listeners = new ArrayList<>();
        }
        return listeners;
    }

    /**
     * INTERNAL:
     * Get the session for this session event manager
     */
    public Session getSession() {
        return session;
    }

    /**
     * PUBLIC:
     * Check if there are any event listeners.
     */
    public boolean hasListeners() {
        return (this.listeners != null) && (!this.listeners.isEmpty());
    }

    /**
     * INTERNAL:
     * Raised for missing descriptors for lazy registration.
     */
    public void missingDescriptor(Class missingClass) {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.MissingDescriptor, getSession());
        event.setResult(missingClass);
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).missingDescriptor(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Raised for stored proc output parameters.
     */
    public void moreRowsDetected(DatabaseCall call) {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.MoreRowsDetected, getSession());
        event.setResult(call);
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).moreRowsDetected(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Raised for stored proc output parameters.
     */
    public void noRowsModified(ModifyQuery query, Object object) {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.NoRowsModified, getSession());
        event.setQuery(query);
        event.setResult(object);
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).noRowsModified(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Raised for stored proc output parameters.
     */
    public void outputParametersDetected(Record outputRow, DatasourceCall call) {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.OutputParametersDetected, getSession());
        event.setResult(outputRow);
        event.setProperty("call", call);
        event.setQuery(call.getQuery());
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).outputParametersDetected(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Post acquire client session.
     */
    public void postAcquireClientSession() {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PostAcquireClientSession, getSession());
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).postAcquireClientSession(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Raised after acquire a connection from a connection pool.
     */
    public void postAcquireConnection(Accessor accessor) {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PostAcquireConnection, getSession());
        event.setResult(accessor);
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).postAcquireConnection(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Raised after acquire a connection from a connection pool.
     */
    public void postAcquireExclusiveConnection(ClientSession clientSession, Accessor accessor) {
        if (!hasListeners()) {
            return;
        }

        SessionEvent event = new SessionEvent(SessionEvent.PostAcquireExclusiveConnection, clientSession);
        event.setResult(accessor);
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).postAcquireExclusiveConnection(event);
        }
    }

    /**
     * INTERNAL:
     * Post acquire unit of work.
     */
    public void postAcquireUnitOfWork() {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PostAcquireUnitOfWork, getSession());
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).postAcquireUnitOfWork(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Post begin transaction.
     */
    public void postBeginTransaction() {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PostBeginTransaction, getSession());
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).postBeginTransaction(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Post commit transaction.
     */
    public void postCommitTransaction() {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PostCommitTransaction, getSession());
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).postCommitTransaction(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Post commit unit of work.
     */
    public void postCommitUnitOfWork() {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PostCommitUnitOfWork, getSession());
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).postCommitUnitOfWork(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Raised after connecting.
     */
    public void postConnect(Accessor accessor) {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PostConnect, getSession());
        event.setResult(accessor);
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).postConnect(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Post execute call.
     */
    public void postExecuteCall(Call call, Object result) {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PostExecuteCall, getSession());
        event.setCall(call);
        event.setResult(result);
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            this.listeners.get(index).postExecuteCall(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Post execute query.
     */
    public void postExecuteQuery(DatabaseQuery query, Object result) {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PostExecuteQuery, getSession());
        event.setQuery(query);
        event.setResult(result);
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            this.listeners.get(index).postExecuteQuery(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Post release client session.
     */
    public void postReleaseClientSession() {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PostReleaseClientSession, getSession());
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).postReleaseClientSession(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Post release unit of work.
     */
    public void postReleaseUnitOfWork() {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PostReleaseUnitOfWork, getSession());
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).postReleaseUnitOfWork(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Post resume unit of work.
     */
    public void postResumeUnitOfWork() {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PostResumeUnitOfWork, getSession());
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).postResumeUnitOfWork(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Post rollback transaction.
     */
    public void postRollbackTransaction() {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PostRollbackTransaction, getSession());
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).postRollbackTransaction(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Pre execute query.
     */
    public void postDistributedMergeUnitOfWorkChangeSet(UnitOfWorkChangeSet changeSet) {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PostDistributedMergeUnitOfWorkChangeSet, getSession());
        event.setProperty("UnitOfWorkChangeSet", changeSet);
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).postDistributedMergeUnitOfWorkChangeSet(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Pre execute query.
     */
    public void postMergeUnitOfWorkChangeSet(UnitOfWorkChangeSet changeSet) {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PostMergeUnitOfWorkChangeSet, getSession());
        event.setProperty("UnitOfWorkChangeSet", changeSet);
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).postMergeUnitOfWorkChangeSet(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Pre begin transaction.
     */
    public void preBeginTransaction() {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PreBeginTransaction, getSession());
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).preBeginTransaction(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Pre calculate UnitOfWork Change Set.
     */
    public void preCalculateUnitOfWorkChangeSet() {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PreCalculateUnitOfWorkChangeSet, getSession());
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).preCalculateUnitOfWorkChangeSet(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Post calculate UnitOfWork Change Set.
     */
    public void postCalculateUnitOfWorkChangeSet(UnitOfWorkChangeSet changeSet) {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PostCalculateUnitOfWorkChangeSet, getSession());
        event.setProperty("UnitOfWorkChangeSet", changeSet);
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).postCalculateUnitOfWorkChangeSet(event);
        }
        endOperationProfile();
    }

    /**
       * INTERNAL:
       * Pre commit transaction.
       */
    public void preCommitTransaction() {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PreCommitTransaction, getSession());
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).preCommitTransaction(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Pre commit unit of work.
     */
    public void preCommitUnitOfWork() {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PreCommitUnitOfWork, getSession());
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).preCommitUnitOfWork(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Pre execute call.
     */
    public void preExecuteCall(Call call) {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PreExecuteCall, getSession());
        event.setCall(call);
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).preExecuteCall(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Pre execute query.
     */
    public void preExecuteQuery(DatabaseQuery query) {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PreExecuteQuery, getSession());
        event.setQuery(query);
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).preExecuteQuery(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Pre login to the session.
     */
    public void preLogin(Session session) {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PreLogin, session);
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).preLogin(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * post login to the session.
     */
    public void postLogin(Session session) {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PostLogin, session);
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).postLogin(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Pre logout to the session.
     */
    public void preLogout(Session session) {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PreLogout, session);
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).preLogout(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * post logout to the session.
     */
    public void postLogout(Session session) {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PostLogout, session);
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).postLogout(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Prepare unit of work.
     */
    public void prepareUnitOfWork() {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PrepareUnitOfWork, getSession());
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).prepareUnitOfWork(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Pre release client session.
     */
    public void preReleaseClientSession() {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PreReleaseClientSession, getSession());
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).preReleaseClientSession(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Raised before release a connection to a connection pool.
     */
    public void preReleaseConnection(Accessor accessor) {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PreReleaseConnection, getSession());
        event.setResult(accessor);
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).preReleaseConnection(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * This event is fired just before a Client Session, with isolated data,
     * releases its Exclusive Connection
     */
    public void preReleaseExclusiveConnection(ClientSession clientSession, Accessor accessor) {
        if (!hasListeners()) {
            return;
        }

        SessionEvent event = new SessionEvent(SessionEvent.PreReleaseExclusiveConnection, clientSession);
        event.setResult(accessor);
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).preReleaseExclusiveConnection(event);
        }
    }

    /**
     * INTERNAL:
     * Pre release unit of work.
     */
    public void preReleaseUnitOfWork() {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PreReleaseUnitOfWork, getSession());
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).preReleaseUnitOfWork(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Pre rollback transaction.
     */
    public void preRollbackTransaction() {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PreRollbackTransaction, getSession());
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).preRollbackTransaction(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Pre merge Distributed UnitOfWorkChangeSet
     */
    public void preDistributedMergeUnitOfWorkChangeSet(UnitOfWorkChangeSet changeSet) {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PreDistributedMergeUnitOfWorkChangeSet, getSession());
        event.setProperty("UnitOfWorkChangeSet", changeSet);
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).preDistributedMergeUnitOfWorkChangeSet(event);
        }
        endOperationProfile();
    }

    /**
     * INTERNAL:
     * Pre merge UnitOfWorkChangeSet
     */
    public void preMergeUnitOfWorkChangeSet(UnitOfWorkChangeSet changeSet) {
        if (!hasListeners()) {
            return;
        }
        startOperationProfile();
        SessionEvent event = new SessionEvent(SessionEvent.PreMergeUnitOfWorkChangeSet, getSession());
        event.setProperty("UnitOfWorkChangeSet", changeSet);
        List<SessionEventListener> listeners = this.listeners;
        int size = listeners.size();
        for (int index = 0; index < size; index++) {
            listeners.get(index).preMergeUnitOfWorkChangeSet(event);
        }
        endOperationProfile();
    }

    /**
     * PUBLIC:
     * Remove the event listener from the session.
     * If session is a broker and the listener was in its list, then its members remove the listener, too.
     */
    public void removeListener(SessionEventListener listener) {
        if (this.session != null) {
            boolean isRemoved = false;
            if (this.session.isConnected()) {
                synchronized(this) {
                    if (this.listeners != null) {
                        ArrayList<SessionEventListener> listenersCopy = new ArrayList(listeners);
                        isRemoved = listenersCopy.remove(listener);
                        if (isRemoved) {
                            this.listeners = listenersCopy;
                        }
                    }
                }
            } else {
                isRemoved = getListeners().remove(listener);
            }
            if (this.session.isSessionBroker() && isRemoved) {
                // remove listener from member sessions
                Iterator<AbstractSession> memberSessions = ((SessionBroker)this.session).getSessionsByName().values().iterator();
                while (memberSessions.hasNext()) {
                    AbstractSession memberSession = memberSessions.next();
                    memberSession.getEventManager().removeListener(listener);
                }
            }
        } else {
            getListeners().remove(listener);
        }
    }

    /**
     * The event listeners will receive all events raised by this session.
     * Also unit of works acquire from this session will inherit the listeners.
     */
    protected void setListeners(List<SessionEventListener> listeners) {
        this.listeners = listeners;
    }

    /**
     * INTERNAL:
     * Set the session for this session event manager
     */
    public void setSession(Session session) {
        this.session = session;
    }

    /**
     * INTERNAL:
     * Start call
     */
    protected void startOperationProfile() {
        if (getSession().isInProfile()) {
            getSession().getProfiler().startOperationProfile(SessionProfiler.SessionEvent);
        }
    }

    /**
     * INTERNAL:
     * End call
     */
    protected void endOperationProfile() {
        if (getSession().isInProfile()) {
            getSession().getProfiler().endOperationProfile(SessionProfiler.SessionEvent);
        }
    }
}
