Skip to content

Commit 052eb0b

Browse files
committed
cleanups to EventListenerGroup(Impl)
Signed-off-by: Gavin King <[email protected]>
1 parent 48fc2ee commit 052eb0b

File tree

2 files changed

+130
-123
lines changed

2 files changed

+130
-123
lines changed

hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerGroupImpl.java

Lines changed: 79 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
package org.hibernate.event.service.internal;
88

99
import java.lang.reflect.Array;
10-
import java.util.Collections;
1110
import java.util.LinkedHashSet;
1211
import java.util.List;
1312
import java.util.Set;
@@ -32,6 +31,8 @@
3231

3332
import static java.util.Arrays.asList;
3433
import static java.util.Collections.emptyList;
34+
import static java.util.Collections.singleton;
35+
import static java.util.concurrent.CompletableFuture.completedFuture;
3536

3637
/**
3738
* Standard EventListenerGroup implementation
@@ -42,8 +43,26 @@
4243
class EventListenerGroupImpl<T> implements EventListenerGroup<T> {
4344

4445
private static final Logger log = Logger.getLogger( EventListenerGroupImpl.class );
45-
private static final Set<DuplicationStrategy> DEFAULT_DUPLICATION_STRATEGIES = Collections.unmodifiableSet( makeDefaultDuplicationStrategy() );
46-
private static final CompletableFuture COMPLETED = CompletableFuture.completedFuture( null );
46+
47+
private static final DuplicationStrategy DEFAULT_DUPLICATION_STRATEGY =
48+
new DuplicationStrategy() {
49+
@Override
50+
public boolean areMatch(Object listener, Object original) {
51+
return listener.getClass().equals( original.getClass() );
52+
}
53+
@Override
54+
public Action getAction() {
55+
return Action.ERROR;
56+
}
57+
};
58+
private static final Set<DuplicationStrategy> DEFAULT_DUPLICATION_STRATEGIES =
59+
singleton( DEFAULT_DUPLICATION_STRATEGY );
60+
61+
private static final CompletableFuture<?> COMPLETED = completedFuture( null );
62+
@SuppressWarnings("unchecked")
63+
private static <R> CompletableFuture<R> nullCompletion() {
64+
return (CompletableFuture<R>) COMPLETED;
65+
}
4766

4867
private final EventType<T> eventType;
4968
private final CallbackRegistry callbackRegistry;
@@ -56,10 +75,7 @@ class EventListenerGroupImpl<T> implements EventListenerGroup<T> {
5675
private volatile T[] listeners = null;
5776
private volatile List<T> listenersAsList = emptyList();
5877

59-
public EventListenerGroupImpl(
60-
EventType<T> eventType,
61-
CallbackRegistry callbackRegistry,
62-
boolean isJpaBootstrap) {
78+
public EventListenerGroupImpl(EventType<T> eventType, CallbackRegistry callbackRegistry, boolean isJpaBootstrap) {
6379
this.eventType = eventType;
6480
this.callbackRegistry = callbackRegistry;
6581
this.isJpaBootstrap = isJpaBootstrap;
@@ -83,7 +99,8 @@ public int count() {
8399

84100
@Override
85101
public void clear() {
86-
//Odd semantics: we're expected (for backwards compatibility) to also clear the default DuplicationStrategy.
102+
//Odd semantics: we're expected (for backwards compatibility)
103+
// to also clear the default DuplicationStrategy.
87104
duplicationStrategies = new LinkedHashSet<>();
88105
setListeners( null );
89106
}
@@ -92,13 +109,10 @@ public void clear() {
92109
// ensure consistency between the two fields by delegating any mutation to both
93110
// fields to this method.
94111
private synchronized void setListeners(T[] newListeners) {
95-
this.listeners = newListeners;
96-
if ( newListeners == null || newListeners.length == 0 ) {
97-
this.listenersAsList = emptyList();
98-
}
99-
else {
100-
this.listenersAsList = asList( newListeners );
101-
}
112+
listeners = newListeners;
113+
listenersAsList = newListeners == null || newListeners.length == 0
114+
? emptyList()
115+
: asList( newListeners );
102116
}
103117

104118
@Override
@@ -107,7 +121,7 @@ public void clearListeners() {
107121
}
108122

109123
@Override
110-
public final <U> void fireLazyEventOnEachListener(final Supplier<U> eventSupplier, final BiConsumer<T,U> actionOnEvent) {
124+
public final <U> void fireLazyEventOnEachListener(Supplier<U> eventSupplier, BiConsumer<T,U> actionOnEvent) {
111125
final T[] ls = listeners;
112126
if ( ls != null && ls.length != 0 ) {
113127
final U event = eventSupplier.get();
@@ -119,7 +133,7 @@ public final <U> void fireLazyEventOnEachListener(final Supplier<U> eventSupplie
119133
}
120134

121135
@Override
122-
public final <U> void fireEventOnEachListener(final U event, final BiConsumer<T,U> actionOnEvent) {
136+
public final <U> void fireEventOnEachListener(U event, BiConsumer<T,U> actionOnEvent) {
123137
final T[] ls = listeners;
124138
if ( ls != null ) {
125139
//noinspection ForLoopReplaceableByForEach
@@ -130,7 +144,7 @@ public final <U> void fireEventOnEachListener(final U event, final BiConsumer<T,
130144
}
131145

132146
@Override
133-
public <U,X> void fireEventOnEachListener(final U event, final X parameter, final EventActionWithParameter<T, U, X> actionOnEvent) {
147+
public <U,X> void fireEventOnEachListener(U event, X parameter, EventActionWithParameter<T, U, X> actionOnEvent) {
134148
final T[] ls = listeners;
135149
if ( ls != null ) {
136150
//noinspection ForLoopReplaceableByForEach
@@ -144,9 +158,9 @@ public <U,X> void fireEventOnEachListener(final U event, final X parameter, fina
144158
public <R, U, RL> CompletionStage<R> fireEventOnEachListener(
145159
final U event,
146160
final Function<RL, Function<U, CompletionStage<R>>> fun) {
147-
CompletionStage<R> ret = COMPLETED;
161+
CompletionStage<R> ret = nullCompletion();
148162
final T[] ls = listeners;
149-
if ( ls != null && ls.length != 0 ) {
163+
if ( ls != null ) {
150164
for ( T listener : ls ) {
151165
//to preserve atomicity of the Session methods
152166
//call apply() from within the arg of thenCompose()
@@ -159,9 +173,9 @@ public <R, U, RL> CompletionStage<R> fireEventOnEachListener(
159173
@Override
160174
public <R, U, RL, X> CompletionStage<R> fireEventOnEachListener(
161175
U event, X param, Function<RL, BiFunction<U, X, CompletionStage<R>>> fun) {
162-
CompletionStage<R> ret = COMPLETED;
176+
CompletionStage<R> ret = nullCompletion();
163177
final T[] ls = listeners;
164-
if ( ls != null && ls.length != 0 ) {
178+
if ( ls != null ) {
165179
for ( T listener : ls ) {
166180
//to preserve atomicity of the Session methods
167181
//call apply() from within the arg of thenCompose()
@@ -173,9 +187,9 @@ public <R, U, RL, X> CompletionStage<R> fireEventOnEachListener(
173187

174188
@Override
175189
public <R, U, RL> CompletionStage<R> fireLazyEventOnEachListener(
176-
final Supplier<U> eventSupplier,
177-
final Function<RL, Function<U, CompletionStage<R>>> fun) {
178-
CompletionStage<R> ret = COMPLETED;
190+
Supplier<U> eventSupplier,
191+
Function<RL, Function<U, CompletionStage<R>>> fun) {
192+
CompletionStage<R> ret = nullCompletion();
179193
final T[] ls = listeners;
180194
if ( ls != null && ls.length != 0 ) {
181195
final U event = eventSupplier.get();
@@ -191,7 +205,8 @@ public <R, U, RL> CompletionStage<R> fireLazyEventOnEachListener(
191205
@Override
192206
public void addDuplicationStrategy(DuplicationStrategy strategy) {
193207
if ( duplicationStrategies == DEFAULT_DUPLICATION_STRATEGIES ) {
194-
duplicationStrategies = makeDefaultDuplicationStrategy();
208+
// At minimum make sure we do not register the same exact listener class multiple times.
209+
duplicationStrategies = new LinkedHashSet<>( DEFAULT_DUPLICATION_STRATEGIES );
195210
}
196211
duplicationStrategies.add( strategy );
197212
}
@@ -212,19 +227,17 @@ public final void appendListeners(T... listeners) {
212227

213228
private void internalAppend(T listener) {
214229
prepareListener( listener );
215-
final T[] listenersRead = this.listeners;
230+
final T[] listenersRead = listeners;
216231
final T[] listenersWrite;
217232

218233
if ( listenersRead == null ) {
219-
//noinspection unchecked
220-
listenersWrite = (T[]) Array.newInstance( eventType.baseListenerInterface(), 1 );
234+
listenersWrite = createListenerArrayForWrite( 1 );
221235
listenersWrite[0] = listener;
222236
}
223237
else {
224238
final int size = listenersRead.length;
225239

226-
//noinspection unchecked
227-
listenersWrite = (T[]) Array.newInstance( eventType.baseListenerInterface(), size+1 );
240+
listenersWrite = createListenerArrayForWrite( size + 1 );
228241

229242
// first copy the existing listeners
230243
System.arraycopy( listenersRead, 0, listenersWrite, 0, size );
@@ -251,19 +264,17 @@ public final void prependListeners(T... listeners) {
251264

252265
private void internalPrepend(T listener) {
253266
prepareListener( listener );
254-
final T[] listenersRead = this.listeners;
267+
final T[] listenersRead = listeners;
255268
final T[] listenersWrite;
256269

257270
if ( listenersRead == null ) {
258-
//noinspection unchecked
259-
listenersWrite = (T[]) Array.newInstance( eventType.baseListenerInterface(), 1 );
271+
listenersWrite = createListenerArrayForWrite( 1 );
260272
listenersWrite[0] = listener;
261273
}
262274
else {
263275
final int size = listenersRead.length;
264276

265-
//noinspection unchecked
266-
listenersWrite = (T[]) Array.newInstance( eventType.baseListenerInterface(), size+1 );
277+
listenersWrite = createListenerArrayForWrite( size + 1 );
267278

268279
// put the new one first
269280
listenersWrite[0] = listener;
@@ -275,13 +286,15 @@ private void internalPrepend(T listener) {
275286
}
276287

277288
private void handleListenerAddition(T listener, Consumer<T> additionHandler) {
278-
final T[] listenersRead = this.listeners;
289+
final T[] listenersRead = listeners;
279290
if ( listenersRead == null ) {
280291
additionHandler.accept( listener );
281292
return;
282293
}
283-
final T[] listenersWrite = (T[]) Array.newInstance( eventType.baseListenerInterface(), listenersRead.length );
284-
System.arraycopy( listenersRead, 0, listenersWrite, 0, listenersRead.length );
294+
int size = listenersRead.length;
295+
296+
final T[] listenersWrite = createListenerArrayForWrite( size );
297+
System.arraycopy( listenersRead, 0, listenersWrite, 0, size );
285298

286299
final boolean debugEnabled = log.isDebugEnabled();
287300

@@ -292,39 +305,36 @@ private void handleListenerAddition(T listener, Consumer<T> additionHandler) {
292305
// strategy's action. Control it returned immediately after applying the action
293306
// on match - meaning no further strategies are checked...
294307

295-
for ( int i = 0; i < listenersRead.length; i++ ) {
308+
for ( int i = 0; i < size; i++ ) {
296309
final T existingListener = listenersRead[i];
297310
if ( debugEnabled ) {
298-
log.debugf(
299-
"Checking incoming listener [`%s`] for match against existing listener [`%s`]",
300-
listener,
301-
existingListener
302-
);
311+
log.debugf( "Checking incoming listener [`%s`] for match against existing listener [`%s`]",
312+
listener, existingListener );
303313
}
304314

305315
if ( strategy.areMatch( listener, existingListener ) ) {
306316
if ( debugEnabled ) {
307-
log.debugf( "Found listener match between `%s` and `%s`", listener, existingListener );
317+
log.debugf( "Found listener match between `%s` and `%s`",
318+
listener, existingListener );
308319
}
309320

310-
switch ( strategy.getAction() ) {
311-
case ERROR: {
321+
final DuplicationStrategy.Action action = strategy.getAction();
322+
switch (action) {
323+
case ERROR:
312324
throw new EventListenerRegistrationException( "Duplicate event listener found" );
313-
}
314-
case KEEP_ORIGINAL: {
325+
case KEEP_ORIGINAL:
315326
if ( debugEnabled ) {
316-
log.debugf( "Skipping listener registration (%s) : `%s`", strategy.getAction(), listener );
327+
log.debugf( "Skipping listener registration (%s) : `%s`",
328+
action, listener );
317329
}
318330
return;
319-
}
320-
case REPLACE_ORIGINAL: {
331+
case REPLACE_ORIGINAL:
321332
if ( debugEnabled ) {
322-
log.debugf( "Replacing listener registration (%s) : `%s` -> `%s`", strategy.getAction(), existingListener, listener );
333+
log.debugf( "Replacing listener registration (%s) : `%s` -> `%s`",
334+
action, existingListener, listener );
323335
}
324336
prepareListener( listener );
325-
326337
listenersWrite[i] = listener;
327-
}
328338
}
329339

330340
// we've found a match - we should return: the match action has already been applied at this point
@@ -335,32 +345,35 @@ private void handleListenerAddition(T listener, Consumer<T> additionHandler) {
335345
}
336346
}
337347

338-
// we did not find any match.. add it
348+
// we did not find any match, add it
339349
checkAgainstBaseInterface( listener );
340350
performInjections( listener );
341351
additionHandler.accept( listener );
342352
}
343353

354+
@SuppressWarnings("unchecked")
355+
private T[] createListenerArrayForWrite(int len) {
356+
return (T[]) Array.newInstance( eventType.baseListenerInterface(), len );
357+
}
358+
344359
private void prepareListener(T listener) {
345360
checkAgainstBaseInterface( listener );
346361
performInjections( listener );
347362
}
348363

349364
private void performInjections(T listener) {
350-
if ( listener instanceof CallbackRegistryConsumer ) {
351-
( (CallbackRegistryConsumer) listener ).injectCallbackRegistry( callbackRegistry );
365+
if ( listener instanceof CallbackRegistryConsumer consumer ) {
366+
consumer.injectCallbackRegistry( callbackRegistry );
352367
}
353-
354-
if ( listener instanceof JpaBootstrapSensitive ) {
355-
( (JpaBootstrapSensitive) listener ).wasJpaBootstrap( isJpaBootstrap );
368+
if ( listener instanceof JpaBootstrapSensitive sensitive ) {
369+
sensitive.wasJpaBootstrap( isJpaBootstrap );
356370
}
357371
}
358372

359373
private void checkAgainstBaseInterface(T listener) {
360374
if ( !eventType.baseListenerInterface().isInstance( listener ) ) {
361-
throw new EventListenerRegistrationException(
362-
"Listener did not implement expected interface [" + eventType.baseListenerInterface().getName() + "]"
363-
);
375+
throw new EventListenerRegistrationException( "Listener did not implement expected interface ["
376+
+ eventType.baseListenerInterface().getName() + "]" );
364377
}
365378
}
366379

@@ -372,26 +385,6 @@ private void checkAgainstBaseInterface(T listener) {
372385
@Override
373386
@Deprecated
374387
public final Iterable<T> listeners() {
375-
return this.listenersAsList;
376-
}
377-
378-
private static Set<DuplicationStrategy> makeDefaultDuplicationStrategy() {
379-
final Set<DuplicationStrategy> duplicationStrategies = new LinkedHashSet<>();
380-
duplicationStrategies.add(
381-
// At minimum make sure we do not register the same exact listener class multiple times.
382-
new DuplicationStrategy() {
383-
@Override
384-
public boolean areMatch(Object listener, Object original) {
385-
return listener.getClass().equals( original.getClass() );
386-
}
387-
388-
@Override
389-
public Action getAction() {
390-
return Action.ERROR;
391-
}
392-
}
393-
);
394-
return duplicationStrategies;
388+
return listenersAsList;
395389
}
396-
397390
}

0 commit comments

Comments
 (0)