Commit 22fbe745 authored by Adam Gausmann's avatar Adam Gausmann

Add implementation for the event system and a logging framework

parent 70a2b708
......@@ -23,6 +23,13 @@
<groupId>ninja.nonemu</groupId>
<artifactId>ircninja</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
......
......@@ -2,6 +2,7 @@ package ninja.nonemu.samurai;
import ninja.nonemu.samurai.event.EventHandler;
import ninja.nonemu.samurai.event.EventSystem;
import org.apache.logging.log4j.Logger;
/**
* Describes the core functionality of a samurai bot.
......@@ -13,5 +14,8 @@ import ninja.nonemu.samurai.event.EventSystem;
*/
public interface Bot {
Logger getLogger();
EventSystem getEventSystem();
}
......@@ -34,6 +34,10 @@
<url>https://gitlab.com/AGausmann/samurai.git</url>
</scm>
<properties>
<log4j.version>2.6.2</log4j.version>
</properties>
<build>
<plugins>
<plugin>
......
......@@ -18,6 +18,12 @@
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package ninja.nonemu.samurai;
import ninja.nonemu.samurai.event.EventSystem;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class BotImpl implements Bot {
private final EventSystemImpl eventSystem;
private final Logger logger;
public BotImpl() {
eventSystem = new EventSystemImpl(this);
logger = LogManager.getLogger();
}
public void init() {
logger.debug("Initializing bot");
eventSystem.init();
}
public void cleanup() {
logger.debug("Cleaning up bot");
eventSystem.cleanup();
}
@Override
public Logger getLogger() {
return logger;
}
@Override
public EventSystem getEventSystem() {
return eventSystem;
}
}
package ninja.nonemu.samurai;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Set;
import java.util.TreeSet;
import ninja.nonemu.samurai.event.Event;
import ninja.nonemu.samurai.event.EventHandler;
import ninja.nonemu.samurai.event.EventSystem;
import ninja.nonemu.samurai.event.Priority;
import org.apache.logging.log4j.Logger;
public class EventSystemImpl implements EventSystem {
private final BotImpl bot;
private final Logger logger;
private final Set<EventHandlerContainer> eventHandlers;
public EventSystemImpl(BotImpl bot) {
this.bot = bot;
logger = bot.getLogger();
eventHandlers = new TreeSet<>();
}
public void init() {
logger.trace("Initializing event system");
}
public void cleanup() {
logger.trace("Cleaning up event system");
eventHandlers.clear();
}
@Override
@SuppressWarnings("unchecked") // We do check, but javac doesn't see that for some reason.
public void registerHandlers(Object o) {
logger.trace("Registering event handlers from " + o.toString());
Class clazz = o.getClass();
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
logger.debug("Registering method " + method.toString());
// If the method is not annotated correctly, skip without failure.
EventHandler annotation = method.getAnnotation(EventHandler.class);
if (annotation == null) {
logger.debug("Method is not annotated; ignoring");
continue;
}
// If the method does not have the proper signature (1 parameter extending Event), give an error message.
if (method.getParameterCount() != 1 && !Event.class.isAssignableFrom(method.getParameterTypes()[0])) {
logger.error("Method is annotated as an EventHandler but does not have the proper signature. " +
"EventHandler methods should take exactly one argument which is Event or a subclass.");
continue;
}
eventHandlers.add(new EventHandlerContainer(o, method, (Class<? extends Event>) method.getParameterTypes()[0], annotation.priority()));
}
}
@Override
public void dispatchEvent(Event event) {
logger.trace("Dispatching event " + event.toString());
for (EventHandlerContainer eventHandler : eventHandlers) {
try {
eventHandler.handleEvent(event);
} catch (InvocationTargetException e) {
logger.error("Error while handling event", e);
}
}
}
private class EventHandlerContainer implements Comparable<EventHandlerContainer> {
Object instance;
Method method;
private final Class<? extends Event> targetClass;
private final Priority priority;
private EventHandlerContainer(Object instance, Method method, Class<? extends Event> targetClass, Priority priority) {
this.instance = instance;
this.method = method;
this.targetClass = targetClass;
this.priority = priority;
}
private void handleEvent(Event event) throws InvocationTargetException {
if (targetClass.isAssignableFrom(event.getClass())) {
try {
method.invoke(instance, event);
} catch (IllegalAccessException e) {
throw new RuntimeException("Method has invalid access level; must be public", e);
}
}
}
@Override
public int compareTo(EventHandlerContainer o) {
return priority.compareTo(o.priority);
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment