HHH-10271 - Add ordinal() method to EventType and change EventListenerRegistryImpl to take advantage of that

(cherry picked from commit 340cee232a)
This commit is contained in:
barreiro 2015-11-03 02:43:51 +00:00 committed by Steve Ebersole
parent feacc4a3b0
commit 0145736fe5
2 changed files with 69 additions and 50 deletions

View File

@ -7,7 +7,6 @@
package org.hibernate.event.service.internal; package org.hibernate.event.service.internal;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -80,11 +79,11 @@ import static org.hibernate.event.spi.EventType.UPDATE;
public class EventListenerRegistryImpl implements EventListenerRegistry { public class EventListenerRegistryImpl implements EventListenerRegistry {
private Map<Class,Object> listenerClassToInstanceMap = new HashMap<Class, Object>(); private Map<Class,Object> listenerClassToInstanceMap = new HashMap<Class, Object>();
private Map<EventType,EventListenerGroupImpl> registeredEventListenersMap = prepareListenerMap(); private EventListenerGroupImpl[] registeredEventListeners = prepareListenerAssociation();
@SuppressWarnings({ "unchecked" }) @SuppressWarnings({ "unchecked" })
public <T> EventListenerGroupImpl<T> getEventListenerGroup(EventType<T> eventType) { public <T> EventListenerGroupImpl<T> getEventListenerGroup(EventType<T> eventType) {
EventListenerGroupImpl<T> listeners = registeredEventListenersMap.get( eventType ); EventListenerGroupImpl<T> listeners = registeredEventListeners[ eventType.ordinal() ];
if ( listeners == null ) { if ( listeners == null ) {
throw new HibernateException( "Unable to find listeners for type [" + eventType.eventName() + "]" ); throw new HibernateException( "Unable to find listeners for type [" + eventType.eventName() + "]" );
} }
@ -93,10 +92,12 @@ public class EventListenerRegistryImpl implements EventListenerRegistry {
@Override @Override
public void addDuplicationStrategy(DuplicationStrategy strategy) { public void addDuplicationStrategy(DuplicationStrategy strategy) {
for ( EventListenerGroupImpl group : registeredEventListenersMap.values() ) { for ( EventListenerGroupImpl group : registeredEventListeners ) {
if ( group != null ) {
group.addDuplicationStrategy( strategy ); group.addDuplicationStrategy( strategy );
} }
} }
}
@Override @Override
public <T> void setListeners(EventType<T> type, Class<? extends T>... listenerClasses) { public <T> void setListeners(EventType<T> type, Class<? extends T>... listenerClasses) {
@ -165,252 +166,252 @@ public class EventListenerRegistryImpl implements EventListenerRegistry {
getEventListenerGroup( type ).prependListeners( listeners ); getEventListenerGroup( type ).prependListeners( listeners );
} }
private static Map<EventType,EventListenerGroupImpl> prepareListenerMap() { private static EventListenerGroupImpl[] prepareListenerAssociation() {
final Map<EventType,EventListenerGroupImpl> workMap = new HashMap<EventType, EventListenerGroupImpl>(); EventListenerGroupImpl[] listenerArray = new EventListenerGroupImpl[ EventType.values().size() ];
// auto-flush listeners // auto-flush listeners
prepareListeners( prepareListeners(
AUTO_FLUSH, AUTO_FLUSH,
new DefaultAutoFlushEventListener(), new DefaultAutoFlushEventListener(),
workMap listenerArray
); );
// create listeners // create listeners
prepareListeners( prepareListeners(
PERSIST, PERSIST,
new DefaultPersistEventListener(), new DefaultPersistEventListener(),
workMap listenerArray
); );
// create-onflush listeners // create-onflush listeners
prepareListeners( prepareListeners(
PERSIST_ONFLUSH, PERSIST_ONFLUSH,
new DefaultPersistOnFlushEventListener(), new DefaultPersistOnFlushEventListener(),
workMap listenerArray
); );
// delete listeners // delete listeners
prepareListeners( prepareListeners(
DELETE, DELETE,
new DefaultDeleteEventListener(), new DefaultDeleteEventListener(),
workMap listenerArray
); );
// dirty-check listeners // dirty-check listeners
prepareListeners( prepareListeners(
DIRTY_CHECK, DIRTY_CHECK,
new DefaultDirtyCheckEventListener(), new DefaultDirtyCheckEventListener(),
workMap listenerArray
); );
// evict listeners // evict listeners
prepareListeners( prepareListeners(
EVICT, EVICT,
new DefaultEvictEventListener(), new DefaultEvictEventListener(),
workMap listenerArray
); );
prepareListeners( prepareListeners(
CLEAR, CLEAR,
workMap listenerArray
); );
// flush listeners // flush listeners
prepareListeners( prepareListeners(
FLUSH, FLUSH,
new DefaultFlushEventListener(), new DefaultFlushEventListener(),
workMap listenerArray
); );
// flush-entity listeners // flush-entity listeners
prepareListeners( prepareListeners(
FLUSH_ENTITY, FLUSH_ENTITY,
new DefaultFlushEntityEventListener(), new DefaultFlushEntityEventListener(),
workMap listenerArray
); );
// load listeners // load listeners
prepareListeners( prepareListeners(
LOAD, LOAD,
new DefaultLoadEventListener(), new DefaultLoadEventListener(),
workMap listenerArray
); );
// resolve natural-id listeners // resolve natural-id listeners
prepareListeners( prepareListeners(
RESOLVE_NATURAL_ID, RESOLVE_NATURAL_ID,
new DefaultResolveNaturalIdEventListener(), new DefaultResolveNaturalIdEventListener(),
workMap listenerArray
); );
// load-collection listeners // load-collection listeners
prepareListeners( prepareListeners(
INIT_COLLECTION, INIT_COLLECTION,
new DefaultInitializeCollectionEventListener(), new DefaultInitializeCollectionEventListener(),
workMap listenerArray
); );
// lock listeners // lock listeners
prepareListeners( prepareListeners(
LOCK, LOCK,
new DefaultLockEventListener(), new DefaultLockEventListener(),
workMap listenerArray
); );
// merge listeners // merge listeners
prepareListeners( prepareListeners(
MERGE, MERGE,
new DefaultMergeEventListener(), new DefaultMergeEventListener(),
workMap listenerArray
); );
// pre-collection-recreate listeners // pre-collection-recreate listeners
prepareListeners( prepareListeners(
PRE_COLLECTION_RECREATE, PRE_COLLECTION_RECREATE,
workMap listenerArray
); );
// pre-collection-remove listeners // pre-collection-remove listeners
prepareListeners( prepareListeners(
PRE_COLLECTION_REMOVE, PRE_COLLECTION_REMOVE,
workMap listenerArray
); );
// pre-collection-update listeners // pre-collection-update listeners
prepareListeners( prepareListeners(
PRE_COLLECTION_UPDATE, PRE_COLLECTION_UPDATE,
workMap listenerArray
); );
// pre-delete listeners // pre-delete listeners
prepareListeners( prepareListeners(
PRE_DELETE, PRE_DELETE,
workMap listenerArray
); );
// pre-insert listeners // pre-insert listeners
prepareListeners( prepareListeners(
PRE_INSERT, PRE_INSERT,
workMap listenerArray
); );
// pre-load listeners // pre-load listeners
prepareListeners( prepareListeners(
PRE_LOAD, PRE_LOAD,
new DefaultPreLoadEventListener(), new DefaultPreLoadEventListener(),
workMap listenerArray
); );
// pre-update listeners // pre-update listeners
prepareListeners( prepareListeners(
PRE_UPDATE, PRE_UPDATE,
workMap listenerArray
); );
// post-collection-recreate listeners // post-collection-recreate listeners
prepareListeners( prepareListeners(
POST_COLLECTION_RECREATE, POST_COLLECTION_RECREATE,
workMap listenerArray
); );
// post-collection-remove listeners // post-collection-remove listeners
prepareListeners( prepareListeners(
POST_COLLECTION_REMOVE, POST_COLLECTION_REMOVE,
workMap listenerArray
); );
// post-collection-update listeners // post-collection-update listeners
prepareListeners( prepareListeners(
POST_COLLECTION_UPDATE, POST_COLLECTION_UPDATE,
workMap listenerArray
); );
// post-commit-delete listeners // post-commit-delete listeners
prepareListeners( prepareListeners(
POST_COMMIT_DELETE, POST_COMMIT_DELETE,
workMap listenerArray
); );
// post-commit-insert listeners // post-commit-insert listeners
prepareListeners( prepareListeners(
POST_COMMIT_INSERT, POST_COMMIT_INSERT,
workMap listenerArray
); );
// post-commit-update listeners // post-commit-update listeners
prepareListeners( prepareListeners(
POST_COMMIT_UPDATE, POST_COMMIT_UPDATE,
workMap listenerArray
); );
// post-delete listeners // post-delete listeners
prepareListeners( prepareListeners(
POST_DELETE, POST_DELETE,
workMap listenerArray
); );
// post-insert listeners // post-insert listeners
prepareListeners( prepareListeners(
POST_INSERT, POST_INSERT,
workMap listenerArray
); );
// post-load listeners // post-load listeners
prepareListeners( prepareListeners(
POST_LOAD, POST_LOAD,
new DefaultPostLoadEventListener(), new DefaultPostLoadEventListener(),
workMap listenerArray
); );
// post-update listeners // post-update listeners
prepareListeners( prepareListeners(
POST_UPDATE, POST_UPDATE,
workMap listenerArray
); );
// update listeners // update listeners
prepareListeners( prepareListeners(
UPDATE, UPDATE,
new DefaultUpdateEventListener(), new DefaultUpdateEventListener(),
workMap listenerArray
); );
// refresh listeners // refresh listeners
prepareListeners( prepareListeners(
REFRESH, REFRESH,
new DefaultRefreshEventListener(), new DefaultRefreshEventListener(),
workMap listenerArray
); );
// replicate listeners // replicate listeners
prepareListeners( prepareListeners(
REPLICATE, REPLICATE,
new DefaultReplicateEventListener(), new DefaultReplicateEventListener(),
workMap listenerArray
); );
// save listeners // save listeners
prepareListeners( prepareListeners(
SAVE, SAVE,
new DefaultSaveEventListener(), new DefaultSaveEventListener(),
workMap listenerArray
); );
// save-update listeners // save-update listeners
prepareListeners( prepareListeners(
SAVE_UPDATE, SAVE_UPDATE,
new DefaultSaveOrUpdateEventListener(), new DefaultSaveOrUpdateEventListener(),
workMap listenerArray
); );
return Collections.unmodifiableMap( workMap ); return listenerArray;
} }
private static <T> void prepareListeners(EventType<T> type, Map<EventType,EventListenerGroupImpl> map) { private static <T> void prepareListeners(EventType<T> type, EventListenerGroupImpl[] listenerArray) {
prepareListeners( type, null, map ); prepareListeners( type, null, listenerArray );
} }
private static <T> void prepareListeners(EventType<T> type, T defaultListener, Map<EventType,EventListenerGroupImpl> map) { private static <T> void prepareListeners(EventType<T> type, T defaultListener, EventListenerGroupImpl[] listenerArray) {
final EventListenerGroupImpl<T> listenerGroup; final EventListenerGroupImpl<T> listenerGroup;
if ( type == EventType.POST_COMMIT_DELETE if ( type == EventType.POST_COMMIT_DELETE
|| type == EventType.POST_COMMIT_INSERT || type == EventType.POST_COMMIT_INSERT
@ -424,7 +425,7 @@ public class EventListenerRegistryImpl implements EventListenerRegistry {
if ( defaultListener != null ) { if ( defaultListener != null ) {
listenerGroup.appendListener( defaultListener ); listenerGroup.appendListener( defaultListener );
} }
map.put( type, listenerGroup ); listenerArray[ type.ordinal() ] = listenerGroup;
} }
} }

View File

@ -12,6 +12,7 @@ import java.security.PrivilegedAction;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
@ -20,7 +21,10 @@ import org.hibernate.HibernateException;
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class EventType<T> { public final class EventType<T> {
private static AtomicInteger typeCounter = new AtomicInteger( 0 );
public static final EventType<LoadEventListener> LOAD = create( "load", LoadEventListener.class ); public static final EventType<LoadEventListener> LOAD = create( "load", LoadEventListener.class );
public static final EventType<ResolveNaturalIdEventListener> RESOLVE_NATURAL_ID = create( "resolve-natural-id", ResolveNaturalIdEventListener.class ); public static final EventType<ResolveNaturalIdEventListener> RESOLVE_NATURAL_ID = create( "resolve-natural-id", ResolveNaturalIdEventListener.class );
@ -131,13 +135,14 @@ public class EventType<T> {
return EVENT_TYPE_BY_NAME_MAP.values(); return EVENT_TYPE_BY_NAME_MAP.values();
} }
private final String eventName; private final String eventName;
private final Class<? extends T> baseListenerInterface; private final Class<? extends T> baseListenerInterface;
private final int ordinal;
private EventType(String eventName, Class<? extends T> baseListenerInterface) { private EventType(String eventName, Class<? extends T> baseListenerInterface) {
this.eventName = eventName; this.eventName = eventName;
this.baseListenerInterface = baseListenerInterface; this.baseListenerInterface = baseListenerInterface;
this.ordinal = typeCounter.getAndIncrement();
} }
public String eventName() { public String eventName() {
@ -152,4 +157,17 @@ public class EventType<T> {
public String toString() { public String toString() {
return eventName(); return eventName();
} }
/**
* EventType is effectively an enumeration. Since there is a known, limited number of possible types, we expose an
* ordinal for each in order to be able to efficiently do associations elsewhere in the codebase (array vs. Map)
*
* For the total number of types, see {@link #values()}
*
* @return An unique ordinal for this {@link EventType}, starting at 0 and up to the number of distinct events
*/
public int ordinal() {
return ordinal;
}
} }