All Downloads are FREE. Search and download functionalities are using the official Maven repository.

uk.co.codera.lang.Announcer Maven / Gradle / Ivy

There is a newer version: 0.0.13
Show newest version
package uk.co.codera.lang;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;

public class Announcer {

    @FunctionalInterface
    public static interface ExceptionHandler {
        void onException(Throwable e);
    }

    private static final class DoNothingExceptionHandler implements ExceptionHandler {
        @Override
        public void onException(Throwable e) {
            // do nothing
        }
    }

    public static final ExceptionHandler EXCEPTION_HANDLER_DO_NOTHING = new DoNothingExceptionHandler();

    private final T proxy;
    private final List listeners = new ArrayList<>();

    private ExceptionHandler exceptionHandler = EXCEPTION_HANDLER_DO_NOTHING;

    private Announcer(Class listenerType) {
        this.proxy = listenerType.cast(Proxy.newProxyInstance(listenerType.getClassLoader(),
                new Class[] { listenerType }, invocationHandler()));
    }

    public static  Announcer to(Class listenerType) {
        return new Announcer<>(listenerType);
    }

    public static  Announcer to(Class listenerType, Iterable listeners) {
        return to(listenerType).addListeners(listeners);
    }

    public Announcer addListener(T listener) {
        this.listeners.add(listener);
        return this;
    }

    public Announcer addListeners(Iterable listeners) {
        for (T listener : listeners) {
            addListener(listener);
        }
        return this;
    }

    public Announcer removeListener(T listener) {
        this.listeners.remove(listener);
        return this;
    }

    public int numberListeners() {
        return this.listeners.size();
    }

    public Announcer useExceptionHandler(ExceptionHandler handler) {
        this.exceptionHandler = handler;
        return this;
    }

    public T announce() {
        return this.proxy;
    }

    private void announce(Method m, Object[] args) {
        for (T listener : this.listeners) {
            invokeListener(listener, m, args);
        }
    }

    @SuppressWarnings("squid:S1166")
    private void invokeListener(T listener, Method method, Object[] args) {
        try {
            method.invoke(listener, args);
        } catch (IllegalAccessException | InvocationTargetException e) {
            Throwable cause = e.getCause();

            if (cause instanceof Error) {
                throw (Error) cause;
            }
            this.exceptionHandler.onException(cause);
        }
    }

    private InvocationHandler invocationHandler() {
        return (proxiedObject, method, args) -> {
            announce(method, args);
            return null;
        };
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy