All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.persistence.descriptors.DescriptorEventManager Maven / Gradle / Ivy

There is a newer version: 5.0.0-B03
Show newest version
/*
 * 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.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.sessions.AbstractSession;
import org.eclipse.persistence.sessions.SessionProfiler;

/**
 * 

Purpose: 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. *

* These events include: *

    *
  • pre/postWrite - occurs when an object is written (occurs even if no changes to the object). *
  • pre/postInsert - occurs when an object is inserted. *
  • pre/postUpdate - occurs when an object is updated (occurs even if no changes to the object). *
  • pre/postDeleted - occurs when an object is deleted. *
  • postBuild/postRefresh - occurs after a object has been built/refreshed from its database row. *
  • aboutTo/Insert/Update - occurs when an object is about to be inserted/update allows for row modification. *
  • postClone - occurs when an object is registered/cloned in a unit of work. *
  • postMerge - occurs when an object is merged with its original in a unit of work. *
* * @see ClassDescriptor */ public class DescriptorEventManager extends CoreDescriptorEventManager implements Cloneable, Serializable { protected ClassDescriptor descriptor; protected AtomicReferenceArray eventSelectors; protected transient AtomicReferenceArray eventMethods; protected transient List eventListeners; // EJB 3.0 support for event listeners. protected transient List defaultEventListeners; protected transient List entityListenerEventListeners; protected transient DescriptorEventListener entityEventListener; /** * Listeners that are fired after all other listeners are fired */ protected transient List internalListeners = new ArrayList<>(); // EJB 3.0 support - cache our parent event managers. protected transient List entityEventManagers; protected transient List 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 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 Object[] runtimeParameters = new Object[1]; runtimeParameters[0] = event; PrivilegedAccessHelper.callDoPrivilegedWithException( () -> PrivilegedAccessHelper.invokeMethod(eventMethod, event.getSource(), runtimeParameters), (ex) -> { if (ex instanceof IllegalAccessException) { return DescriptorException.illegalAccessWhileEventExecution(eventMethod.getName(), getDescriptor(), ex); } if (ex instanceof IllegalArgumentException) { return DescriptorException.illegalArgumentWhileObsoleteEventExecute(eventMethod.getName(), getDescriptor(), ex); } if (ex instanceof InvocationTargetException) { return DescriptorException.targetInvocationWhileEventExecution(eventMethod.getName(), getDescriptor(), ex); } return new RuntimeException(String.format("Invocation of %s method failed", eventMethod.getName()), ex); } ); } 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 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 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 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 getEntityListenerEventListeners() { if (entityListenerEventListeners == null) { entityListenerEventListeners = new CopyOnWriteArrayList<>(); } return entityListenerEventListeners; } /** * PUBLIC: * Returns the Listener objects that have been added. * * @see #addListener(DescriptorEventListener) */ public List getEventListeners() { // Lazy initialize to avoid unnecessary enumerations. if (eventListeners == null) { eventListeners = new CopyOnWriteArrayList<>(); } return eventListeners; } protected AtomicReferenceArray getEventMethods() { //Lazy Initialized to prevent Null Pointer exception after serialization if (this.eventMethods == null) { this.eventMethods = newAtomicReferenceArray(NumberOfEvents); } return eventMethods; } protected AtomicReferenceArray 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 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 entityListenerEventListeners = entityListenerEventManagers.get(index).getEntityListenerEventListeners(); for (int i = 0; i < entityListenerEventListeners.size(); i++) { DescriptorEventListener listener = 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 eventListeners) { if (eventListeners instanceof CopyOnWriteArrayList) { this.eventListeners = eventListeners; } else { this.eventListeners = new CopyOnWriteArrayList(eventListeners); } } protected void setEventMethods(AtomicReferenceArray eventMethods) { this.eventMethods = eventMethods; } protected void setEventSelectors(AtomicReferenceArray 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 AtomicReferenceArray newAtomicReferenceArray(final int length) { final AtomicReferenceArray 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 AtomicReferenceArray newAtomicReferenceArray(final AtomicReferenceArray src) { final int length = src.length(); final AtomicReferenceArray array = new AtomicReferenceArray<>(length); for (int index = 0; index < length; array.set(index, src.get(index++))); return array; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy