/*
 * 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
//     12/14/2017-3.0 Tomas Kraus
//       - 291546: Performance degradation due to usage of Vector in DescriptorEventManager
package org.eclipse.persistence.descriptors;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicReferenceArray;

import org.eclipse.persistence.core.descriptors.CoreDescriptorEventManager;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedMethodInvoker;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.sessions.SessionProfiler;

/**
 * <p><b>Purpose</b>: The event manager allows for a descriptor to specify that
 * an object should be notified when a EclipseLink event occurs.  It also determines
 * how the object will be notified. To specify an event a method name can be
 * registered to be called on the object when the event occurs. Events can be
 * used to extend the EclipseLink reading and writing behavior.
 * <p>
 * These events include:
 * <ul>
 * <li> pre/postWrite - occurs when an object is written (occurs even if no changes to the object).
 * <li> pre/postInsert - occurs when an object is inserted.
 * <li> pre/postUpdate - occurs when an object is updated (occurs even if no changes to the object).
 * <li> pre/postDeleted - occurs when an object is deleted.
 * <li> postBuild/postRefresh - occurs after a object has been built/refreshed from its database row.
 * <li> aboutTo/Insert/Update - occurs when an object is about to be inserted/update allows for row modification.
 * <li> postClone - occurs when an object is registered/cloned in a unit of work.
 * <li> postMerge - occurs when an object is merged with its original in a unit of work.
 * </ul>
 *
 * @see ClassDescriptor
 */
public class DescriptorEventManager extends CoreDescriptorEventManager<DescriptorEvent> implements Cloneable, Serializable {
    protected ClassDescriptor descriptor;
    protected AtomicReferenceArray<String> eventSelectors;
    protected transient AtomicReferenceArray<Method> eventMethods;
    protected transient List<DescriptorEventListener> eventListeners;

    // EJB 3.0 support for event listeners.
    protected transient List<DescriptorEventListener> defaultEventListeners;
    protected transient List<DescriptorEventListener> entityListenerEventListeners;
    protected transient DescriptorEventListener entityEventListener;
    /**
     * Listeners that are fired after all other listeners are fired
     */
    protected transient List<DescriptorEventListener>  internalListeners = new ArrayList<>();

    // EJB 3.0 support - cache our parent event managers.
    protected transient List<DescriptorEventManager> entityEventManagers;
    protected transient List<DescriptorEventManager> entityListenerEventManagers;

    // EJB 3.0 support for event listener configuration flags.
    protected boolean excludeDefaultListeners;
    protected boolean excludeSuperclassListeners;

    //JPA project caching support.  Holds DescriptorEventListener representations for serialization/storage.
    protected List<SerializableDescriptorEventHolder> descriptorEventHolders;

    /** PERF: Cache if any events listener exist. */
    protected boolean hasAnyEventListeners;
    public static final int PreWriteEvent = 0;
    public static final int PostWriteEvent = 1;
    public static final int PreDeleteEvent = 2;
    public static final int PostDeleteEvent = 3;
    public static final int PreInsertEvent = 4;
    public static final int PostInsertEvent = 5;
    public static final int PreUpdateEvent = 6;
    public static final int PostUpdateEvent = 7;
    public static final int PostBuildEvent = 8;
    public static final int PostRefreshEvent = 9;
    public static final int PostCloneEvent = 10;
    public static final int PostMergeEvent = 11;
    public static final int AboutToInsertEvent = 12;
    public static final int AboutToUpdateEvent = 13;

    // CR#2660080 was missing aboutToDelete
    public static final int AboutToDeleteEvent = 14;

    // EJB 3.0 events
    public static final int PrePersistEvent = 15;
    public static final int PreRemoveEvent = 16;
    public static final int PreUpdateWithChangesEvent = 17;

    protected static final int NumberOfEvents = 18;

    /**
     * INTERNAL:
     * Returns a new DescriptorEventManager for the specified ClassDescriptor.
     */
    public DescriptorEventManager() {
        this.eventSelectors = newAtomicReferenceArray(NumberOfEvents);
        this.eventMethods = newAtomicReferenceArray(NumberOfEvents);
        this.hasAnyEventListeners = false;
        this.excludeDefaultListeners = false;
        this.excludeSuperclassListeners = false;
    }

    /**
     * PUBLIC:
     * EJB 3.0 support for default listeners.
     */
    public void addDefaultEventListener(DescriptorEventListener listener) {
        getDefaultEventListeners().add(listener);
    }

    /**
     * PUBLIC:
     * EJB 3.0 support for lifecycle callback events defined on an entity
     * listener class.
     */
    public void addEntityListenerEventListener(DescriptorEventListener listener) {
        getEntityListenerEventListeners().add(listener);
    }

    /**
     * PUBLIC:
     * Listener objects can be registered with the event manager to be notified
     * when an event occurs on any instance of the descriptor's class.
     */
    public void addListener(DescriptorEventListener listener) {
        getEventListeners().add(listener);
        setHasAnyEventListeners(true);
    }

    /**
     * INTERNAL:
     *
     */
    public void addInternalListener(DescriptorEventListener listener) {
        if (internalListeners==null) {
            internalListeners = new ArrayList<>();
        }
        internalListeners.add(listener);
        setHasAnyEventListeners(true); // ensure that events are generated
    }

    /**
     * INTERNAL:
     *
     */
    public void addEntityListenerHolder(SerializableDescriptorEventHolder holder) {
        this.getDescriptorEventHolders().add(holder);
    }

    /**
     * INTERNAL:
     * Clone the manager and its private parts.
     */
    @Override
    public Object clone() {
        try {
            DescriptorEventManager clone = (DescriptorEventManager)super.clone();
            clone.setEventSelectors(newAtomicReferenceArray(getEventSelectors()));
            clone.setEventMethods(newAtomicReferenceArray(getEventMethods()));
            clone.setEventListeners(getEventListeners());
            return clone;
        } catch (Exception exception) {
            throw new AssertionError(exception);
        }
    }

    /**
     * INTERNAL:
     * This method was added to allow JPA project caching so that DescriptorEventListeners could be
     * serialized and re-added to the EventManager using a SerializableDescriptorEventHolder.
     */
    public void processDescriptorEventHolders(AbstractSession session, ClassLoader classLoader) {
        if (this.descriptorEventHolders != null) {
            for (SerializableDescriptorEventHolder holder: descriptorEventHolders) {
                holder.addListenerToEventManager(getDescriptor(), session, classLoader);
            }
        }
    }

    /**
     * INTERNAL:
     * EJB 3.0 support. Returns true if this event manager should exclude the
     * invocation of the default listeners for this descriptor.
     */
    public boolean excludeDefaultListeners() {
        return excludeDefaultListeners;
    }

    /**
     * INTERNAL:
     * EJB 3.0 support. Returns true is this event manager should exclude the
     * invocation of the listeners defined by the entity listener classes for
     * the superclasses of this descriptor.
     */
    public boolean excludeSuperclassListeners() {
        return excludeSuperclassListeners;
    }

    /**
     * INTERNAL:
     * Execute the given selector with the event as argument.
     * @exception DescriptorException - the method cannot be found or executed
     */
    @Override
    public void executeEvent(DescriptorEvent event) throws DescriptorException {
        try {
            event.getSession().startOperationProfile(SessionProfiler.DescriptorEvent);
            // CR#3467758, ensure the descriptor is set on the event.
            event.setDescriptor(getDescriptor());
            notifyListeners(event);
            notifyEJB30Listeners(event);

            if (event.getSource() instanceof DescriptorEventListener) {
                // Allow the object itself to implement the interface.
                notifyListener((DescriptorEventListener)event.getSource(), event);
                return;
            }

            Method eventMethod = getEventMethods().get(event.getEventCode());
            if (eventMethod == null) {
                return;
            }

            // Now that I have the method, I need to invoke it
            try {
                Object[] runtimeParameters = new Object[1];
                runtimeParameters[0] = event;
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    try {
                        AccessController.doPrivileged(new PrivilegedMethodInvoker(eventMethod, event.getSource(), runtimeParameters));
                    } catch (PrivilegedActionException exception) {
                        Exception throwableException = exception.getException();
                        if (throwableException instanceof IllegalAccessException) {
                            throw DescriptorException.illegalAccessWhileEventExecution(eventMethod.getName(), getDescriptor(), throwableException);
                        } else {
                            throw DescriptorException.targetInvocationWhileEventExecution(eventMethod.getName(), getDescriptor(), throwableException);
                        }
                    }
                } else {
                    PrivilegedAccessHelper.invokeMethod(eventMethod, event.getSource(), runtimeParameters);
                }
            } catch (IllegalAccessException exception) {
                throw DescriptorException.illegalAccessWhileEventExecution(eventMethod.getName(), getDescriptor(), exception);
            } catch (IllegalArgumentException exception) {
                throw DescriptorException.illegalArgumentWhileObsoleteEventExecute(eventMethod.getName(), getDescriptor(), exception);
            } catch (InvocationTargetException exception) {
                throw DescriptorException.targetInvocationWhileEventExecution(eventMethod.getName(), getDescriptor(), exception);
            }
        } finally {
            event.getSession().endOperationProfile(SessionProfiler.DescriptorEvent);
        }
    }

    /**
     * Find the method corresponding to the event selector. The method MUST take
     * DescriptorEvent as argument, Session is also supported as argument for
     * backward compatibility.
     */
    protected Method findMethod(int selector) throws DescriptorException {
        Class[] declarationParameters = new Class[1];
        declarationParameters[0] = ClassConstants.DescriptorEvent_Class;
        String methodName = getEventSelectors().get(selector);

        try {
            return Helper.getDeclaredMethod(getDescriptor().getJavaClass(), methodName, declarationParameters);
        } catch (NoSuchMethodException exception) {
            throw DescriptorException.noSuchMethodOnFindObsoleteMethod(methodName, getDescriptor(), exception);
        } catch (SecurityException exception) {
            throw DescriptorException.securityOnFindMethod(methodName, getDescriptor(), exception);
        }
    }

    /**
     * INTERNAL:
     * bug 251180 - Missing method org.eclipse.persistence.descriptors.DescriptorEventManager#setAboutToDeleteSelector
     */
    public String getAboutToDeleteSelector() {
        return getEventSelectors().get(AboutToDeleteEvent);
    }

    /**
     * INTERNAL:
     */
    public String getAboutToInsertSelector() {
        return getEventSelectors().get(AboutToInsertEvent);
    }

    /**
     * INTERNAL:
     */
    public String getAboutToUpdateSelector() {
        return getEventSelectors().get(AboutToUpdateEvent);
    }

    /**
     * INTERNAL:
     * EJB 3.0 support. Returns the default listeners.
     */
    public List<DescriptorEventListener> getDefaultEventListeners() {
        if (defaultEventListeners == null) {
            defaultEventListeners = new CopyOnWriteArrayList<>();
        }
        return defaultEventListeners;
    }

    /**
     * INTERNAL:
     */
    protected ClassDescriptor getDescriptor() {
        return descriptor;
    }

    /**
     * INTERNAL:
     * used by JPA project caching to store DescriptorEventListener representations that can build the underlying
     * DescriptorEventListener and add it to the EventManager.
     */
    public List<SerializableDescriptorEventHolder> getDescriptorEventHolders() {
        if (descriptorEventHolders == null) {
            descriptorEventHolders = new CopyOnWriteArrayList<>();
        }
        return descriptorEventHolders;
    }

    /**
     * INTERNAL:
     * used by JPA project caching to store DescriptorEventListener representations that can build the underlying
     * DescriptorEventListener and add it to the EventManager.
     */
    public void setDescriptorEventHolders(List<SerializableDescriptorEventHolder> descriptorEventHolders) {
        this.descriptorEventHolders = descriptorEventHolders;
    }

    /**
     * INTERNAL:
     * EJB 3.0 support. Returns the entity event listener.
     */
    public DescriptorEventListener getEntityEventListener() {
        return entityEventListener;
    }

    /**
     * INTERNAL:
     * EJB 3.0 support. Returns the entity listener event listeners.
     */
    public List<DescriptorEventListener> getEntityListenerEventListeners() {
        if (entityListenerEventListeners == null) {
            entityListenerEventListeners = new CopyOnWriteArrayList<>();
        }
        return entityListenerEventListeners;
    }

    /**
     * PUBLIC:
     * Returns the Listener objects that have been added.
     *
     * @see #addListener(DescriptorEventListener)
     */
    public List<DescriptorEventListener> getEventListeners() {
        // Lazy initialize to avoid unnecessary enumerations.
        if (eventListeners == null) {
            eventListeners = new CopyOnWriteArrayList<>();
        }
        return eventListeners;
    }

    protected AtomicReferenceArray<Method> getEventMethods() {
        //Lazy Initialized to prevent Null Pointer exception after serialization
        if (this.eventMethods == null) {
            this.eventMethods = newAtomicReferenceArray(NumberOfEvents);
        }
        return eventMethods;
    }

    protected AtomicReferenceArray<String> getEventSelectors() {
        if (this.eventSelectors == null) {
            this.eventSelectors = newAtomicReferenceArray(NumberOfEvents);
        }
        return eventSelectors;
    }

    /**
     * PUBLIC:
     *  The name of the method called after an object is built
     */
    public String getPostBuildSelector() {
        return getEventSelectors().get(PostBuildEvent);
    }

    /**
     * PUBLIC:
     *  The name of the method called after an object is cloned
     */
    public String getPostCloneSelector() {
        return getEventSelectors().get(PostCloneEvent);
    }

    /**
     * PUBLIC:
     *  The name of the method called after an object is deleted
     */
    public String getPostDeleteSelector() {
        return getEventSelectors().get(PostDeleteEvent);
    }

    /**
     * PUBLIC:
     *  The name of the method called after an object is inserted
     */
    public String getPostInsertSelector() {
        return getEventSelectors().get(PostInsertEvent);
    }

    /**
     * PUBLIC:
     *  The name of the method called after an object is merged
     */
    public String getPostMergeSelector() {
        return getEventSelectors().get(PostMergeEvent);
    }

    /**
     * PUBLIC:
     *  The name of the method called after an object is refreshed
     */
    public String getPostRefreshSelector() {
        return getEventSelectors().get(PostRefreshEvent);
    }

    /**
     * PUBLIC:
     *  The name of the method called after an object is updated
     */
    public String getPostUpdateSelector() {
        return getEventSelectors().get(PostUpdateEvent);
    }

    /**
     * PUBLIC:
     *  The name of the method called after an object is written
     */
    public String getPostWriteSelector() {
        return getEventSelectors().get(PostWriteEvent);
    }

    /**
     * PUBLIC:
     *  The name of the method called before the create operation is applied to an object
     */
    public String getPrePersistSelector() {
        return getEventSelectors().get(PrePersistEvent);
    }

  /**
     * PUBLIC:
     *  The name of the method called before an object is deleted
     */
    public String getPreDeleteSelector() {
        return getEventSelectors().get(PreDeleteEvent);
    }

    /**
     * PUBLIC:
     *  The name of the method called before an object is inserted
     */
    public String getPreInsertSelector() {
        return getEventSelectors().get(PreInsertEvent);
    }

    /**
     * PUBLIC:
     *  The name of the method called before the remove operation is applied to an object
     */
    public String getPreRemoveSelector() {
        return getEventSelectors().get(PreRemoveEvent);
    }

  /**
     * PUBLIC:
     *  The name of the method called before an object is updated
     */
    public String getPreUpdateSelector() {
        return getEventSelectors().get(PreUpdateEvent);
    }

    /**
     * PUBLIC:
     *  The name of the method called before an object is written
     */
    public String getPreWriteSelector() {
        return getEventSelectors().get(PreWriteEvent);
    }

    /**
     * INTERNAL:
     * Return if the event manager has any event listeners, or event methods.
     * If nothing is listening to event they can be avoided.
     */
    @Override
    public boolean hasAnyEventListeners() {
        // Check listeners in case of collection added to directly as occurs
        // for aggregates that have a clone of the event manager but not the
        // listeners.
        return hasAnyEventListeners || hasAnyListeners();
    }

    protected boolean hasAnyListeners() {
        return (eventListeners != null) && (!eventListeners.isEmpty());
    }

    /**
     * INTERNAL:
     * This method will return true, if this event manager has default listeners
     * and does not exclude them. Default listeners are always added to every
     * event manager to allow users to turn them on a later time if so desired.
     */
    public boolean hasDefaultEventListeners() {
        return defaultEventListeners != null && ! defaultEventListeners.isEmpty() && ! excludeDefaultListeners;
    }

    /**
     * INTERNAL:
     * EJB 3.0 support. Return true if this event manager has any entity event
     * listeners.
     */
    public boolean hasEntityEventListener() {
        return entityEventListener != null;
    }

    /**
     * INTERNAL:
     * Internal event support.  Return true if this event manager has any internal
     * listener event listeners.
     */
    public boolean hasInternalEventListeners() {
        return internalListeners != null && !internalListeners.isEmpty();
    }

    /**
     * INTERNAL:
     * EJB 3.0 support. Return true if this event manager has any entity
     * listener event listeners.
     */
    public boolean hasEntityListenerEventListeners() {
        return entityListenerEventListeners != null && !entityListenerEventListeners.isEmpty();
    }

    /**
     * INTERNAL:
     * Configure inherited selectors.
     */
    public void initialize(AbstractSession session) {
        setHasAnyEventListeners(false);
        // Initialize the EJB 3.0 supported listeners.
        initializeEJB30EventManagers();
        if (hasEntityEventListener() || hasEntityListenerEventListeners() || hasDefaultEventListeners() || hasInternalEventListeners()) {
            setHasAnyEventListeners(true);
        }

        // Initialize if events are required at all.
        if (hasAnyListeners() || DescriptorEventListener.class.isAssignableFrom(getDescriptor().getJavaClass())) {
            setHasAnyEventListeners(true);
        }

        final AtomicReferenceArray<String> selectors = getEventSelectors();
        for (int index = 0; index < NumberOfEvents; index++) {
            if (selectors.get(index) != null) {
                setHasAnyEventListeners(true);
                getEventMethods().set(index, findMethod(index));
            }
        }

        // Inherit all parent defined event method
        // Do NOT inherit the listener as the events are broadcast to the parent.
        if (getDescriptor().isChildDescriptor()) {
            DescriptorEventManager parentEventManager = getDescriptor().getInheritancePolicy().getParentDescriptor().getEventManager();
            if (parentEventManager.hasAnyEventListeners()) {
                setHasAnyEventListeners(true);
            }

            for (int index = 0; index < NumberOfEvents; index++) {
                if ((selectors.get(index) == null) && (parentEventManager.getEventSelectors().get(index) != null)) {
                    setHasAnyEventListeners(true);
                    selectors.set(index, parentEventManager.getEventSelectors().get(index));
                    getEventMethods().set(index, parentEventManager.getEventMethods().get(index));
                }
            }
        }
    }

    /**
     * INTERNAL:
     * EJB 3.0 support. Builds our chains of descriptor event managers that will
     * need to be notified. The chains are cache so we only need to build them
     * once.
     */
    protected void initializeEJB30EventManagers() {
        entityEventManagers = new CopyOnWriteArrayList<>();
        entityListenerEventManagers = new CopyOnWriteArrayList<>();

        if (hasEntityEventListener()) {
            entityEventManagers.add(this);
        }

        if (hasEntityListenerEventListeners()) {
            entityListenerEventManagers.add(this);
        }

        ClassDescriptor currentDescriptor = getDescriptor();
        boolean excludeEntityListeners = excludeSuperclassListeners();

        while (currentDescriptor.isChildDescriptor()) {
            currentDescriptor = currentDescriptor.getInheritancePolicy().getParentDescriptor();

            DescriptorEventManager eventManager = currentDescriptor.getEventManager();

            if (eventManager.hasEntityEventListener()) {
                entityEventManagers.add(eventManager);
            }

            if (eventManager.hasEntityListenerEventListeners()) {
                if (!excludeEntityListeners) {
                    entityListenerEventManagers.add(eventManager);
                }
            }

            excludeEntityListeners = eventManager.excludeSuperclassListeners();
        }
    }

    /**
     * INTERNAL:
     * Notify the EJB 3.0 event listeners.
     */
    protected void notifyEJB30Listeners(DescriptorEvent event) {
        // Step 1 - notify our default listeners.
        if (hasDefaultEventListeners()) {
            for (int i = 0; i < getDefaultEventListeners().size(); i++) {
                DescriptorEventListener listener = getDefaultEventListeners().get(i);
                notifyListener(listener, event);
            }
        }

        // Step 2 - Notify the Entity Listener's first, top -> down.
        for (int index = entityListenerEventManagers.size() - 1; index >= 0; index--) {
            List<DescriptorEventListener> entityListenerEventListeners = entityListenerEventManagers.get(index).getEntityListenerEventListeners();

            for (int i = 0; i < entityListenerEventListeners.size(); i++) {
                DescriptorEventListener listener = (DescriptorEventListener) entityListenerEventListeners.get(i);
                notifyListener(listener, event);
            }
        }

        // Step 3 - Notify the Entity event listeners. top -> down, unless
        // they are overridden in a subclass.
        for (int index = entityEventManagers.size() - 1; index >= 0; index--) {
            DescriptorEventListener entityEventListener = entityEventManagers.get(index).getEntityEventListener();

            if (! entityEventListener.isOverriddenEvent(event, entityEventManagers)) {
                notifyListener(entityEventListener, event);
            }
        }

        // Step 4 - Notify internal listeners.
        if (internalListeners != null) { // could be null after serialization
            for (DescriptorEventListener listener : internalListeners) {
                notifyListener(listener, event);
            }
        }
    }

    /**
     * INTERNAL:
     * Big ugly case statement to notify listeners.
     */
    protected void notifyListener(DescriptorEventListener listener, DescriptorEvent event) throws DescriptorException {
        switch (event.getEventCode()) {
        case PreWriteEvent:
            listener.preWrite(event);
            break;
        case PostWriteEvent:
            listener.postWrite(event);
            break;
        case PreDeleteEvent:
            listener.preDelete(event);
            break;
        case PostDeleteEvent:
            listener.postDelete(event);
            break;
        case PreInsertEvent:
            listener.preInsert(event);
            break;
        case PostInsertEvent:
            listener.postInsert(event);
            break;
        case PreUpdateEvent:
            listener.preUpdate(event);
            break;
        case PostUpdateEvent:
            listener.postUpdate(event);
            break;
        case PostMergeEvent:
            listener.postMerge(event);
            break;
        case PostCloneEvent:
            listener.postClone(event);
            break;
        case PostBuildEvent:
            listener.postBuild(event);
            break;
        case PostRefreshEvent:
            listener.postRefresh(event);
            break;
        case AboutToInsertEvent:
            listener.aboutToInsert(event);
            break;
        case AboutToUpdateEvent:
            listener.aboutToUpdate(event);
            break;
        case AboutToDeleteEvent:
            listener.aboutToDelete(event);
            break;
        case PrePersistEvent:
            listener.prePersist(event);
            break;
        case PreRemoveEvent:
            listener.preRemove(event);
            break;
        case PreUpdateWithChangesEvent:
            listener.preUpdateWithChanges(event);
            break;
        default:
            throw DescriptorException.invalidDescriptorEventCode(event, getDescriptor());
        }
    }

    /**
     * INTERNAL:
     * Notify the event listeners.
     */
    public void notifyListeners(DescriptorEvent event) {
        if (hasAnyListeners()) {
            for (int index = 0; index < getEventListeners().size(); index++) {
                DescriptorEventListener listener = getEventListeners().get(index);
                notifyListener(listener, event);
            }
        }

        // Also must notify any inherited listeners.
        if (getDescriptor().isChildDescriptor()) {
            getDescriptor().getInheritancePolicy().getParentDescriptor().getEventManager().notifyListeners(event);
        }
    }

    /**
     * INTERNAL:
     * Used to initialize a remote DescriptorEventManager.
     */
    public void remoteInitialization(AbstractSession session) {
        this.eventMethods = newAtomicReferenceArray(NumberOfEvents);
        initialize(session);
    }

    /**
     * PUBLIC:
     * Remove a event listener.
     */
    public void removeListener(DescriptorEventListener listener) {
        getEventListeners().remove(listener);
    }

    /**
     * PUBLIC:
     * A method can be registered to be called when an object's row it about to
     * be inserted. This uses the optional event argument of the DatabaseRow.
     * This is different from pre/postInsert because it occurs after the row has
     * already been built. This event can be used to modify the row before
     * insert, such as adding a user inserted by.
     */
    //bug 251180: Missing method org.eclipse.persistence.descriptors.DescriptorEventManager#setAboutToDeleteSelector
    public void setAboutToDeleteSelector(String aboutToDeleteSelector) {
        getEventSelectors().set(AboutToDeleteEvent, aboutToDeleteSelector);
    }

    /**
     * PUBLIC:
     * A method can be registered to be called when an object's row it about to
     * be inserted. This uses the optional event argument of the DatabaseRow.
     * This is different from pre/postInsert because it occurs after the row has
     * already been built. This event can be used to modify the row before
     * insert, such as adding a user inserted by.
     */
    public void setAboutToInsertSelector(String aboutToInsertSelector) {
        getEventSelectors().set(AboutToInsertEvent, aboutToInsertSelector);
    }

    /**
     * PUBLIC:
     * A method can be registered to be called when an object's row it about to
     * be updated. This uses the optional event argument of the DatabaseRow.
     * This is different from pre/postUpdate because it occurs after the row has
     * already been built, and it ONLY called if the update is required (changed
     * within a unit of work), as the other occur ALWAYS. This event can be used
     * to modify the row before insert, such as adding a user inserted by.
     */
    public void setAboutToUpdateSelector(String aboutToUpdateSelector) {
        getEventSelectors().set(AboutToUpdateEvent, aboutToUpdateSelector);
    }

    /**
     * INTERNAL:
     * Set the descriptor.
     */
    public void setDescriptor(ClassDescriptor descriptor) {
        this.descriptor = descriptor;
    }

    /**
     * PUBLIC:
     * EJB 3.0 support for lifecycle callback events defined on an entity class.
     */
    public void setEntityEventListener(DescriptorEventListener listener) {
        this.entityEventListener = listener;
    }

    protected void setEventListeners(List<DescriptorEventListener> eventListeners) {
        if (eventListeners instanceof CopyOnWriteArrayList) {
            this.eventListeners = eventListeners;
        } else {
            this.eventListeners = new CopyOnWriteArrayList(eventListeners);
        }
    }

    protected void setEventMethods(AtomicReferenceArray<Method> eventMethods) {
        this.eventMethods = eventMethods;
    }

    protected void setEventSelectors(AtomicReferenceArray<String> eventSelectors) {
        this.eventSelectors = eventSelectors;
    }

    /**
     * INTERNAL:
     * EJB 3.0 support. Default listeners apply to all entities in a persistence
     * unit. Set this flag to true to exclude the invocation of the default
     * listeners for this descriptor.
     */
    public void setExcludeDefaultListeners(boolean excludeDefaultListeners) {
        this.excludeDefaultListeners = excludeDefaultListeners;
    }

    /**
     * INTERNAL:
     * EJB 3.0 support. If multiple entity classes in an inheritance hierarchy
     * define entity listeners, the listeners defined for a superclass are
     * invoked before the listeners defined for its subclasses. Set this flag
     * to true to exclude the invocation of the listeners defined by the entity
     * listener classes for the superclasses of this descriptor.
     */
    public void setExcludeSuperclassListeners(boolean excludeSuperclassListeners) {
        this.excludeSuperclassListeners = excludeSuperclassListeners;
    }

    /**
     * INTERNAL:
     * Set if the event manager has any event listeners, or event methods.
     * If nothing is listening to event they can be avoided.
     */
    protected void setHasAnyEventListeners(boolean hasAnyEventListeners) {
        this.hasAnyEventListeners = hasAnyEventListeners;
    }

    /**
     * PUBLIC:
     * A method can be registered to be called on a object that has just been
     * built from the database. This uses the optional event argument for the
     * DatabaseRow. This event can be used to correctly initialize an object's
     * non-persistent attributes or to perform complex optimizations or
     * mappings. This event is called whenever an object is built.
     */
    public void setPostBuildSelector(String postBuildSelector) {
        getEventSelectors().set(PostBuildEvent, postBuildSelector);
    }

    /**
     * PUBLIC:
     * A method can be registered to be called on a object that has just been
     * cloned into a unit of work. This uses the optional event argument for the
     * original object (the source object is the clone). This event can be used
     * to correctly initialize an object's non-persistent attributes.
     */
    public void setPostCloneSelector(String postCloneSelector) {
        getEventSelectors().set(PostCloneEvent, postCloneSelector);
    }

    /**
     * PUBLIC:
     * A method can be registered to be called on a object that has just been
     * deleted from the database. This event can notify/remove any dependents
     * on the object.
     */
    public void setPostDeleteSelector(String postDeleteSelector) {
        getEventSelectors().set(PostDeleteEvent, postDeleteSelector);
    }

    /**
     * PUBLIC:
     * A method can be registered to be called on a object that has just been
     * inserted into the database. This event can be used to notify any
     * dependent on the object, or to update information not accessible until
     * the object has been inserted.
     */
    public void setPostInsertSelector(String postInsertSelector) {
        getEventSelectors().set(PostInsertEvent, postInsertSelector);
    }

    /**
     * PUBLIC:
     * A method can be registered to be called on a object that has just been
     * merge from a unit of work. This uses the optional event argument of the
     * original object which is the object being merged from, the source object
     * is the object being merged into. This event can be used to correctly
     * initialize an object's non-persistent attributes.
     */
    public void setPostMergeSelector(String postMergeSelector) {
        getEventSelectors().set(PostMergeEvent, postMergeSelector);
    }

    /**
     * PUBLIC:
     * A method can be registered to be called on a object that has just been
     * refreshed from the database. This uses the optional event argument of
     * the DatabaseRow. This event can be used to correctly initialize an
     * object's non-persistent attributes or to perform complex optimizations or
     * mappings. This event is only called on refreshes of existing objects.
     */
    public void setPostRefreshSelector(String postRefreshSelector) {
        getEventSelectors().set(PostRefreshEvent, postRefreshSelector);
    }

    /**
     * PUBLIC:
     * A method can be registered to be called on a object that has just been
     * updated into the database.
     */
    public void setPostUpdateSelector(String postUpdateSelector) {
        getEventSelectors().set(PostUpdateEvent, postUpdateSelector);
    }

    /**
     * PUBLIC:
     * A method can be registered to be called on a object that has just been
     * written to the database. This event is raised on any registered object
     * in a unit of work, even if it has not changed, refer to the
     * "aboutToUpdate" selector if it is required for the event to be raised
     * only when the object has been changed. This will be called on all inserts
     * and updates, after the "postInsert/Update" event has been raised. This
     * event can be used to notify any dependent on the object.
     */
    public void setPostWriteSelector(String postWriteSelector) {
        getEventSelectors().set(PostWriteEvent, postWriteSelector);
    }

    /**
     * PUBLIC:
     * A method can be registered to be called on a object that is going to be
     * deleted from the database. This event can notify/remove any dependents
     * on the object.
     */
    public void setPreDeleteSelector(String preDeleteSelector) {
        getEventSelectors().set(PreDeleteEvent, preDeleteSelector);
    }

    /**
     * PUBLIC:
     * A method can be registered to be called on a object that is going to be
     * inserted into the database. This event can be used to notify any
     * dependent on the object or acquire the object's id through a custom
     * mechanism.
     */
    public void setPreInsertSelector(String preInsertSelector) {
        getEventSelectors().set(PreInsertEvent, preInsertSelector);
    }

    /**
     * PUBLIC:
     * A method can be registered to be called on a object when that object has
     * the create operation applied to it.
     */
    public void setPrePersistSelector(String prePersistSelector) {
        getEventSelectors().set(PrePersistEvent, prePersistSelector);
    }

    /**
     * PUBLIC:
     * A method can be registered to be called on a object when that object has
     * the remove operation applied to it.
     */
    public void setPreRemoveSelector(String preRemoveSelector) {
        getEventSelectors().set(PreRemoveEvent, preRemoveSelector);
    }

    /**
     * PUBLIC:
     * A method can be registered to be called on a object that is going to be
     * updated into the database. This event is raised on any registered object
     * in a unit of work, even if it has not changed, refer to the
     * "aboutToUpdate" selector if it is required for the event to be raised
     * only when the object has been changed. This event can be used to notify
     * any dependent on the object.
     */
    public void setPreUpdateSelector(String preUpdateSelector) {
        getEventSelectors().set(PreUpdateEvent, preUpdateSelector);
    }

    /**
     * PUBLIC:
     * A method can be registered to be called on a object that is going to be
     * written to the database. This event is raised on any registered object
     * in a unit of work, even if it has not changed, refer to the
     * "aboutToUpdate" selector if it is required for the event to be raised
     * only when the object has been changed. This will be called on all inserts
     * and updates, before the "preInsert/Update" event has been raised. This
     * event can be used to notify any dependent on the object.
     */
    public void setPreWriteSelector(String preWriteSelector) {
        getEventSelectors().set(PreWriteEvent, preWriteSelector);
    }

    /**
     * Create an instance of {@link java.util.concurrent.atomic.AtomicIntegerArray} initialized with {@code NullEvent} values.
     *
     * @param length length of the array.
     * @return initialized instance of {@link java.util.concurrent.atomic.AtomicIntegerArray}
     */
    private static <T> AtomicReferenceArray<T> newAtomicReferenceArray(final int length) {
        final AtomicReferenceArray<T> array = new AtomicReferenceArray<>(length);
        for (int index = 0; index < length; array.set(index++, null));
        return array;
    }

    /**
     * Create an instance of {@link java.util.concurrent.atomic.AtomicIntegerArray} initialized with content of provided array.
     *
     * @param src source array.
     * @return initialized instance of {@link java.util.concurrent.atomic.AtomicIntegerArray}
     */
    private static <T> AtomicReferenceArray<T> newAtomicReferenceArray(final AtomicReferenceArray<T> src) {
        final int length = src.length();
        final AtomicReferenceArray<T> array = new AtomicReferenceArray<>(length);
        for (int index = 0; index < length; array.set(index, src.get(index++)));
        return array;
    }

}
