package jalse.misc; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.LinkedHashSet; import java.util.Objects; import java.util.Set; /** * Provides a thread-safe way to store and process listeners. Listener set takes in the defining * listener {@code interface} and allows you to invoke the defined method upon the whole group via a * {@link ListenerSet#getProxy()}. * * @author Elliot Ford * * @see Proxy#newProxyInstance(ClassLoader, Class[], InvocationHandler) * * @param <T> * Listener {@code interface}. */ public class ListenerSet<T> extends LinkedHashSet<T>implements InvocationHandler { private static final long serialVersionUID = 1437345792255852480L; private final T proxy; /** * Creates a new instance of listener set for the supplied listener type. * * @param clazz * Listener type to store. */ public ListenerSet(final Class<? super T> clazz) { this(clazz, null); } /** * Creates a new instance of listener set for the supplied listener type. * * @param clazz * Listener type to store. * @param listeners * Starting listeners. */ @SuppressWarnings("unchecked") public ListenerSet(final Class<? super T> clazz, final Set<? extends T> listeners) { proxy = (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[] { clazz }, this); if (listeners != null) { addAll(listeners); } } @Override public boolean add(final T e) { return super.add(Objects.requireNonNull(e)); } /** * Gets the group proxy for easy invocation of methods upon the group. * * @return Listener group proxy. */ public T getProxy() { return proxy; } @Override public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { for (final T t : this) { method.invoke(t, args); } return null; } @Override public boolean remove(final Object o) { return super.remove(Objects.requireNonNull(o)); } }