Package com.godshawk.lib.event.handlers

Source Code of com.godshawk.lib.event.handlers.EventManager

/*
* LibGodshawk - General-purpose Java library
* Copyright (C) 2014-2015 godshawk
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package com.godshawk.lib.event.handlers;

import com.godshawk.lib.annotations.reflection.event.EventListener;
import com.godshawk.lib.event.EventBase;
import com.godshawk.lib.event.EventObject;
import com.godshawk.lib.interfaces.util.updaters.IToggleable;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

@SuppressWarnings("unused")
public class EventManager {
    private static EventManager instance;
    private final Vector<EventObject> listeners;

    private EventManager() {
        listeners = new Vector<>();
    }

    public static EventManager getInstance() {
        return instance == null ? instance = new EventManager() : instance;
    }

    public void registerListener(Object listener) {
        if (exists(listener)) {
            return;
        }

        Class<?> listenerClass = listener.getClass();

        List<Method> methodsWithAnnotation = new ArrayList<>();
        Arrays.stream(listenerClass.getDeclaredMethods()).
                filter(m -> m.isAnnotationPresent(EventListener.class)).sequential().forEach(methodsWithAnnotation::add);

        Set<Class<? extends EventBase>> eventClasses = new HashSet<>();
        for (Method method : methodsWithAnnotation) {
            EventListener annotation = method.getDeclaredAnnotation(EventListener.class);
            Class<? extends EventBase> eventClass = annotation.event();
            if (!eventClasses.contains(eventClass)) {
                eventClasses.add(eventClass);
            }
        }

        for (Class<? extends EventBase> eventClass : eventClasses) {
            synchronized (listeners) {
                listeners.add(new EventObject(listener, eventClass,
                        methodsWithAnnotation.stream().
                                filter(m -> m.getDeclaredAnnotation(EventListener.class).event().equals(eventClass)).sequential().
                                toArray(Method[]::new)));
            }
        }
    }

    public void unregisterListener(Object listener) {
        if (!exists(listener)) {
            return;
        }
        synchronized (listeners) {
            Arrays.stream(getExisting(listener)).forEach(listeners::remove);
        }
    }

    private boolean exists(Object o) {
        return listeners.parallelStream().filter(l -> l.getInvokee().equals(o)).toArray(Object[]::new).length > 0;
    }

    private Object[] getExisting(Object o) {
        return listeners.parallelStream().filter(l -> l.getInvokee().equals(o)).toArray(Object[]::new);
    }

    public Vector<EventObject> getListeners() {
        synchronized (listeners) {
            return listeners;
        }
    }

    public <T extends EventBase> T fire(T event) {
        synchronized (listeners) {
            for (EventObject eo : listeners) {
                if (!eo.getEventClass().equals(event.getClass())) {
                    continue;
                }
                if (eo.getInvokee() instanceof IToggleable) {
                    if (!((IToggleable) eo.getInvokee()).isState()) {
                        continue;
                    }
                }
                for (EventObject.MethodObject m : eo.getMethods()) {
                    try {
                        if (m.getParamCount() == 0) {
                            m.getMethod().invoke(eo.getInvokee());
                        } else if (m.getParamCount() == 1) {
                            m.getMethod().invoke(eo.getInvokee(), event);
                        } else {
                            throw new IllegalArgumentException(
                                    String.format("Method %s in class %s (%s) has the wrong number of parameters (%s)!",
                                            m.getMethod().getName(), eo.getInvokee().getClass().getSimpleName(),
                                            eo.getInvokee().toString(), m.getParamCount())
                            );
                        }
                    } catch (IllegalAccessException | InvocationTargetException ex) {
                        ex.printStackTrace();
                    }
                }
            }
        }
        return event;
    }
}
TOP

Related Classes of com.godshawk.lib.event.handlers.EventManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.