package org.sef4j.core.helpers.senders;
import java.util.Collection;
import org.sef4j.core.api.EventSender;
import org.sef4j.core.api.EventProvider;
import org.sef4j.core.util.CopyOnWriteUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* composite of EventSender<T> to add/remove several listener EventSender<T>
* this class is mutable, and thread-safe
*
* It may be confusing to have both role EventSender and EventProvider ...
* see other more restrictive classes
*
*
* <PRE>
* addEventListener()
* -------->
* removeEventListener()
* -------->
* +------------+
* sendEvent(..) | | target[0].sendEvent(..)
* ----------> | targets[] | ---------->
* +------------+ target[1].sendEvent(..)
* ---------->
* ...
* target[N-1].sendEvent(..)
* ---------->
* </PRE>
* @param <T>
*/
public class DefaultEventProvider<T> implements EventSender<T>, EventProvider<T> {
private static final Logger LOG = LoggerFactory.getLogger(DefaultEventProvider.class);
private static final EventSender<?>[] EMPTY_ARRAY = new EventSender<?>[0];
/** copy-on-write */
@SuppressWarnings("unchecked")
private EventSender<T>[] targets = (EventSender<T>[]) EMPTY_ARRAY;
private Object lock = new Object();
// ------------------------------------------------------------------------
public DefaultEventProvider() {
}
// ------------------------------------------------------------------------
public void sendEvent(T event) {
final EventSender<T>[] to = targets;
final int len = to.length;
for (int i = 0; i < len; i++) {
try {
to[i].sendEvent(event);
} catch(Exception ex) {
LOG.error("Failed to sendEvent to " + to[i]
+ ", ex:" + ex.getMessage() + " ... ignore, no rethrow!");
}
}
}
public void sendEvents(Collection<T> events) {
final EventSender<T>[] to = targets;
final int len = to.length;
for (int i = 0; i < len; i++) {
try {
to[i].sendEvents(events);
} catch(Exception ex) {
LOG.error("Failed to sendEvents to " + to[i]
+ ", ex:" + ex.getMessage() + " ... ignore, no rethrow!");
}
}
}
@SuppressWarnings("unchecked")
public void addEventListener(EventSender<T> listener) {
if (listener == null) throw new IllegalArgumentException();
synchronized(lock) {
this.targets = CopyOnWriteUtils.newWithAdd(EventSender.class, targets, listener);
}
}
@SuppressWarnings("unchecked")
public void removeEventListener(EventSender<T> listener) {
if (listener == null) throw new IllegalArgumentException();
synchronized(lock) {
this.targets = CopyOnWriteUtils.newWithRemove(EventSender.class, targets, listener);
}
}
public int getEventListenerCount() {
return targets.length;
}
}