/*
 * 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;

/**
 * <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(DataRecord 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);
        }
    }
}
