package org.sef4j.core.api.ioeventchain; import java.io.Closeable; import org.sef4j.core.api.EventSender; import org.sef4j.core.api.def.ioevenchain.InputEventChainDef; import org.sef4j.core.helpers.senders.DefaultEventProvider; import org.sef4j.core.util.Handle; import org.sef4j.core.util.factorydef.AbstractSharedStartableObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * chain of EventSender (EventSender->EventSender->EventSender) * * instance of this class are managed by ObjectByDefRepository * and are unique for the given corresponding InputEventChainDef * * to obtain output events from this chain; * <code> * EventSender<T> myEventCallback = ... * InputEventChain<T> inputChain = ... // repository.register(def); * * ListenerHandle<T> subscr = inputChain.registerEventListener(myEventCallback); * ... * ... // receive events: calls myEventCallback.sendEvents(..) * ... * inputChain.unregisterEventListener(subscr); * </code> */ public abstract class InputEventChain<T> extends AbstractSharedStartableObject<InputEventChainDef> { private static final Logger LOG = LoggerFactory.getLogger(InputEventChain.class); protected DefaultEventProvider<T> innerEventProvider = new DefaultEventProvider<T>(); // ------------------------------------------------------------------------ public InputEventChain(String displayName) { super(displayName); } // ------------------------------------------------------------------------ public ListenerHandle<T> registerEventListener(EventSender<T> listener) { innerEventProvider.addEventListener(listener); Handle handle = registerStart(); return new ListenerHandle<T>(this, handle, listener); } public void unregisterEventListener(ListenerHandle<T> handle) { innerEventProvider.removeEventListener(handle.listener); unregisterStop(handle.handle); } // TODO use only in sub-classes ??? public EventSender<T> getInnerEventSender() { return innerEventProvider; } // ------------------------------------------------------------------------ public static class ListenerHandle<T> implements Closeable { private InputEventChain<T> target; private Handle handle; private EventSender<T> listener; private ListenerHandle(InputEventChain<T> target, Handle handle, EventSender<T> listener) { this.target = target; this.handle = handle; this.listener = listener; } @Override protected void finalize() throws Throwable { if (target != null) { LOG.warn("detected unreleased resource ... force close()!"); try { close(); } catch(Exception ex) { LOG.error("Failed ... ignore, no rethrow!", ex); } } super.finalize(); } @Override public void close() { if (target != null && handle != null) { target.unregisterEventListener(this); } this.handle = null; } } }