Система событий
This commit is contained in:
@@ -22,7 +22,7 @@ public class Main {
|
||||
/**
|
||||
* Запуск сервера на порту 8881
|
||||
*/
|
||||
Server server = new Server(settings, manager, Configuration.class);
|
||||
Server server = new Server(settings, manager);
|
||||
server.start();
|
||||
}
|
||||
}
|
||||
17
src/main/java/com/rosetta/im/event/Cancelable.java
Normal file
17
src/main/java/com/rosetta/im/event/Cancelable.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package com.rosetta.im.event;
|
||||
|
||||
public interface Cancelable {
|
||||
|
||||
/**
|
||||
* Отменено ли событие
|
||||
* @return true, если событие отменено
|
||||
*/
|
||||
boolean isCanceled();
|
||||
|
||||
/**
|
||||
* Установить отмену события
|
||||
* @param canceled true, если событие должно быть отменено
|
||||
*/
|
||||
void setCanceled(boolean canceled);
|
||||
|
||||
}
|
||||
18
src/main/java/com/rosetta/im/event/Event.java
Normal file
18
src/main/java/com/rosetta/im/event/Event.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package com.rosetta.im.event;
|
||||
|
||||
public class Event {
|
||||
|
||||
private String name;
|
||||
|
||||
public Event() {}
|
||||
|
||||
public String getEventName() {
|
||||
if(this.name == null) {
|
||||
this.name = this.getClass().getSimpleName();
|
||||
}
|
||||
return this.name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
13
src/main/java/com/rosetta/im/event/EventException.java
Normal file
13
src/main/java/com/rosetta/im/event/EventException.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package com.rosetta.im.event;
|
||||
|
||||
public class EventException extends Exception {
|
||||
|
||||
public EventException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public EventException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
||||
12
src/main/java/com/rosetta/im/event/EventHandler.java
Normal file
12
src/main/java/com/rosetta/im/event/EventHandler.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package com.rosetta.im.event;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface EventHandler {
|
||||
|
||||
}
|
||||
120
src/main/java/com/rosetta/im/event/EventManager.java
Normal file
120
src/main/java/com/rosetta/im/event/EventManager.java
Normal file
@@ -0,0 +1,120 @@
|
||||
package com.rosetta.im.event;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Менеджер событий
|
||||
*/
|
||||
public class EventManager {
|
||||
|
||||
private Set<Listener> listeners;
|
||||
|
||||
public EventManager() {
|
||||
this.listeners = new HashSet<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрация слушателя событий
|
||||
* @param listener Слушатель событий
|
||||
*/
|
||||
public void registerListener(Listener listener) {
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаление слушателя событий
|
||||
* @param listener Слушатель событий
|
||||
*/
|
||||
public void unregisterListener(Listener listener) {
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить все зарегистрированные слушатели событий
|
||||
* @return Множество слушателей событий
|
||||
*/
|
||||
public Set<Listener> getListeners() {
|
||||
return this.listeners;
|
||||
}
|
||||
|
||||
/**
|
||||
* Вызывает событие и обрабатывает исключения
|
||||
* @param event Событие для вызова
|
||||
* @return true, если событие отменено
|
||||
*/
|
||||
public boolean callEvent(Event event) {
|
||||
try {
|
||||
return fireEvent(event);
|
||||
} catch (EventException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Запускает событие, уведомляя всех зарегистрированных слушателей, возвращает true если событие отменено
|
||||
* @param event Событие для запуска
|
||||
* @return true, если событие отменено
|
||||
* @throws EventException Ошибка при обработке события
|
||||
* @throws Exception Общая ошибка при вызове метода
|
||||
*/
|
||||
private boolean fireEvent(Event event) throws EventException, Exception {
|
||||
for(Listener listener : this.listeners) {
|
||||
/**
|
||||
* Получаем все методы в Listener с аннотацией @EventHandler
|
||||
*/
|
||||
List<Method> methods = getMethodsWithAnnotation(listener.getClass(), EventHandler.class);
|
||||
for(Method method : methods) {
|
||||
/**
|
||||
* Проверяем, что метод принимает один параметр того же типа, что и событие
|
||||
*/
|
||||
if(method.getParameterCount() == 1
|
||||
&& method.getParameterTypes()[0].isAssignableFrom(event.getClass())) {
|
||||
/**
|
||||
* Если параметры совпадают и они одного типа - вызываем событие
|
||||
*/
|
||||
method.setAccessible(true);
|
||||
method.invoke(listener, event);
|
||||
/**
|
||||
* Если событие отменяемое - проверяем его статус
|
||||
*/
|
||||
if(event instanceof Cancelable) {
|
||||
Cancelable cancelableEvent = (Cancelable) event;
|
||||
if(cancelableEvent.isCanceled()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
/**
|
||||
* Если метод обрабатывающий событие
|
||||
* реализован неправильно - выбрасываем исключение
|
||||
*/
|
||||
throw new EventException("Invalid event params");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private List<Method> getMethodsWithAnnotation(Class<?> clazz, Class<? extends Annotation> annotation) {
|
||||
List<Method> methods = new ArrayList<>();
|
||||
for (Method method : clazz.getDeclaredMethods()) {
|
||||
if (method.isAnnotationPresent(annotation)) {
|
||||
methods.add(method);
|
||||
}
|
||||
}
|
||||
return methods;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
25
src/main/java/com/rosetta/im/event/EventPriority.java
Normal file
25
src/main/java/com/rosetta/im/event/EventPriority.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package com.rosetta.im.event;
|
||||
|
||||
/**
|
||||
* Приоритет события
|
||||
* Указывает на то, в каком порядке обработаются два одинаковых события
|
||||
*/
|
||||
public enum EventPriority {
|
||||
LOW(0),
|
||||
MEDIUM(1),
|
||||
HIGH(2);
|
||||
|
||||
private final int priority;
|
||||
|
||||
EventPriority(int priority) {
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить приоритет
|
||||
* @return Приоритет события
|
||||
*/
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
}
|
||||
10
src/main/java/com/rosetta/im/event/Listener.java
Normal file
10
src/main/java/com/rosetta/im/event/Listener.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package com.rosetta.im.event;
|
||||
|
||||
/**
|
||||
* Слушатель событий
|
||||
*/
|
||||
public interface Listener {
|
||||
/**
|
||||
* Пустой интерфейс для обозначения слушателя событий
|
||||
*/
|
||||
}
|
||||
Reference in New Issue
Block a user