Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
cyklon73 committed Dec 4, 2023
0 parents commit 4dc2bbc
Show file tree
Hide file tree
Showing 11 changed files with 434 additions and 0 deletions.
38 changes: 38 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/

### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr

### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache

### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/

### VS Code ###
.vscode/

### Mac OS ###
.DS_Store
25 changes: 25 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>de.cyklon</groupId>
<artifactId>JEvent</artifactId>
<version>1.0</version>

<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>22.0.0</version>
</dependency>
</dependencies>

</project>
23 changes: 23 additions & 0 deletions src/main/java/de/cyklon/jevent/Cancellable.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package de.cyklon.jevent;

/**
* This interface can be implemented to make an event cancelable
* <p>
* If the event is marked as canceld, all listeners that would be executed afterwards will not be executed unless ignoreCancelled is set to true in the @{@link EventHandler} annotation.
* @author <a href="https://github.com/cyklon73">Cyklon73</a>
*/
public interface Cancellable {

/**
* returns true if the event was marked as canceled
* @return true if event was canceled
*/
boolean isCancelled();

/**
* sets the canceled status of the event to the specified value
* @param cancelled the new status
*/
void setCancelled(boolean cancelled);

}
25 changes: 25 additions & 0 deletions src/main/java/de/cyklon/jevent/CancellableEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package de.cyklon.jevent;

import org.jetbrains.annotations.Nullable;

public abstract class CancellableEvent extends Event implements Cancellable {

private boolean cancelled = false;

protected CancellableEvent() {
}

protected CancellableEvent(@Nullable String name) {
super(name);
}

@Override
public boolean isCancelled() {
return cancelled;
}

@Override
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
}
57 changes: 57 additions & 0 deletions src/main/java/de/cyklon/jevent/Event.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package de.cyklon.jevent;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
* the event base class.
* Extend this class to create your own event
* @author <a href="https://github.com/cyklon73">Cyklon73</a>
*/
public abstract class Event {

/**
* the event name
*/
private final String name;


/**
* constructs the event, with the class name as the event name
*/
protected Event() {
this(null);
}

/**
* constructs the event with a specific name
* @param name the event name. If it is null, it is set to the class name
*/
protected Event(@Nullable String name) {
this.name = name==null ? this.getClass().getSimpleName() : name;
}

/**
* call all listeners for this event
* @see EventManager#callEvent(Event)
* @return true if the event was canceled
*/
public boolean callEvent() {
JEvent.MANAGER.callEvent(this);
if (this instanceof Cancellable) return ((Cancellable)this).isCancelled();
return false;
}

/**
* @return the name of the Event
*/
@NotNull
public String getEventName() {
return name;
}

@Override
public String toString() {
return Event.class + "(" + getEventName() + ")";
}
}
59 changes: 59 additions & 0 deletions src/main/java/de/cyklon/jevent/EventException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package de.cyklon.jevent;


/**
* is called when an error occurs in the event system
* @author <a href="https://github.com/cyklon73">Cyklon73</a>
*/
public class EventException extends RuntimeException {

private final Throwable cause;

/**
* Constructs a new EventException based on the given Exception
*
* @param throwable Exception that triggered this Exception
*/
public EventException(Throwable throwable) {
cause = throwable;
}

/**
* Constructs a new EventException
*/
public EventException() {
cause = null;
}

/**
* Constructs a new EventException with the given message
*
* @param cause The exception that caused this
* @param message The message
*/
public EventException(Throwable cause, String message) {
super(message);
this.cause = cause;
}

/**
* Constructs a new EventException with the given message
*
* @param message The message
*/
public EventException(String message) {
super(message);
cause = null;
}

/**
* If applicable, returns the Exception that triggered this Exception
*
* @return Inner exception, or null if one does not exist
*/
@Override
public Throwable getCause() {
return cause;
}

}
43 changes: 43 additions & 0 deletions src/main/java/de/cyklon/jevent/EventHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package de.cyklon.jevent;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* An annotation to mark methods as being event handler methods
* @author <a href="https://github.com/cyklon73">Cyklon73</a>
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface EventHandler {

byte LOWEST = -2;
byte LOW = -1;
byte NORMAL = 0;
byte HIGH = 1;
byte HIGHEST = 2;
byte MONITOR = 3;


/**
* Define the priority of the event.
* <p>
* Lowest priority to the Highest priority executed.
* @return the priority
*/
byte priority() default NORMAL;

/**
* Define if the handler ignores a cancelled event.
* <p>
* If ignoreCancelled is true and the event is cancelled, the method is
* not called. Otherwise, the method is always called.
*
* @return whether cancelled events should be ignored
*/
boolean ignoreCancelled() default false;


}
35 changes: 35 additions & 0 deletions src/main/java/de/cyklon/jevent/EventManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package de.cyklon.jevent;

import org.jetbrains.annotations.NotNull;

/**
* The EventManager to manage and execute events
* @author <a href="https://github.com/cyklon73">Cyklon73</a>
*/
public sealed interface EventManager permits JEvent {

/**
* registers all methods annotated with @{@link EventHandler}
* @param obj the object from which events are to be registered
*/
void registerListener(@NotNull Object obj);

/**
* removes all listeners that have the type of the specified class
* @param clazz The type of listener Object to be removed
*/
void unregisterListener(@NotNull Class<?> clazz);

/**
* removes all listeners
*/
void unregisterAll();


/**
* calls the passed event and executes all registered listeners, as well as all listeners that were registered for a superclass of the event
* @param event the event to be executed
*/
void callEvent(@NotNull Event event);

}
73 changes: 73 additions & 0 deletions src/main/java/de/cyklon/jevent/Handler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package de.cyklon.jevent;

import org.jetbrains.annotations.NotNull;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

/**
* The handler object represents a single event listener method
* @author <a href="https://github.com/cyklon73">Cyklon73</a>
*/
class Handler implements Comparable<Handler> {

private final Object listener;
private final Method handler;
private Class<? extends Event> eventType = null;
private final byte priority;
private final boolean ignoreCancelled;

@SuppressWarnings("unchecked")
private Handler(Object listener, Method handler, byte priority, boolean ignoreCancelled) {
this.listener = listener;
this.handler = handler;
this.handler.setAccessible(true);
for (Class<?> parameterType : handler.getParameterTypes()) {
if (Event.class.isAssignableFrom(parameterType)) {
this.eventType = (Class<? extends Event>) parameterType;
break;
}
}
if (eventType==null) throw new EventException("the method must have an event as a parameter!");
this.priority = priority;
this.ignoreCancelled = ignoreCancelled;
}

public Object getListener() {
return listener;
}

public boolean isSuitableHandler(Class<? extends Event> event) {
return eventType.isAssignableFrom(event);
}

public void invoke(Event event) {
if (event instanceof Cancellable && ((Cancellable)event).isCancelled() && !ignoreCancelled) return;
if (isSuitableHandler(event.getClass())) {
try {
handler.invoke(listener, event);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new EventException(e);
}
}
}

@Override
public int compareTo(@NotNull Handler o) {
return Byte.compare(o.priority, this.priority);
}

public static Collection<Handler> getHandlers(Object listener) {
Method[] methods = listener.getClass().getDeclaredMethods();
List<Handler> handlers = new LinkedList<>();
for (Method handler : methods) {
EventHandler annotation = handler.getAnnotation(EventHandler.class);
if (annotation==null) continue;
handlers.add(new Handler(listener, handler, annotation.priority(), annotation.ignoreCancelled()));
}
return handlers;
}
}
Loading

0 comments on commit 4dc2bbc

Please sign in to comment.