All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.rx.core.EventTarget Maven / Gradle / Ivy
package org.rx.core;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.rx.beans.FlagsEnum;
import org.rx.beans.NEnum;
import java.lang.reflect.Field;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.BiConsumer;
import static org.rx.core.Contract.*;
public interface EventTarget> {
@Slf4j
class Delegate, TArgs extends EventArgs> implements BiConsumer {
@Getter
private final List> invocationList = new CopyOnWriteArrayList<>();
@SuppressWarnings(NonWarning)
@Override
public void accept(TSender target, TArgs args) {
require(target, args);
FlagsEnum flags = target.eventFlags();
if (flags.has(EventTarget.EventFlags.ThreadSafe)) {
synchronized (target) {
innerRaise(target, args, flags);
}
return;
}
innerRaise(target, args, flags);
}
private void innerRaise(TSender target, TArgs args, FlagsEnum flags) {
for (BiConsumer biConsumer : invocationList) {
try {
biConsumer.accept(target, args);
} catch (Exception e) {
if (!flags.has(EventTarget.EventFlags.Quietly)) {
throw e;
}
log.warn("innerRaise", e);
}
}
}
}
@RequiredArgsConstructor
enum EventFlags implements NEnum {
None(0),
ThreadSafe(1),
Quietly(1 << 1),
DynamicAttach(1 << 2);
@Getter
private final int value;
}
default FlagsEnum eventFlags() {
return EventFlags.None.flags();
}
default void attachEvent(String eventName, BiConsumer event) {
attachEvent(eventName, event, true);
}
@SuppressWarnings(NonWarning)
@SneakyThrows
default void attachEvent(String eventName, BiConsumer event, boolean combine) {
require(eventName);
Field field = Reflects.getFields(this.getClass()).firstOrDefault(p -> p.getName().equals(eventName));
if (field == null) {
if (!eventFlags().has(EventFlags.DynamicAttach)) {
throw new InvalidOperationException(String.format("Event %s not defined", eventName));
}
EventListener.getInstance().attach(this, eventName, event, combine);
return;
}
field.set(this, combine ? combine((BiConsumer) field.get(this), event) : event);
}
@SuppressWarnings(NonWarning)
@SneakyThrows
default void detachEvent(String eventName, BiConsumer event) {
require(eventName);
Field field = Reflects.getFields(this.getClass()).firstOrDefault(p -> p.getName().equals(eventName));
if (field == null) {
if (!eventFlags().has(EventFlags.DynamicAttach)) {
throw new InvalidOperationException(String.format("Event %s not defined", eventName));
}
EventListener.getInstance().detach(this, eventName, event);
return;
}
field.set(this, remove((BiConsumer) field.get(this), event));
}
@SuppressWarnings(NonWarning)
@SneakyThrows
default void raiseEvent(String eventName, TArgs args) {
require(eventName);
Field field = Reflects.getFields(this.getClass()).firstOrDefault(p -> p.getName().equals(eventName));
if (field == null) {
if (!eventFlags().has(EventFlags.DynamicAttach)) {
throw new InvalidOperationException(String.format("Event %s not defined", eventName));
}
EventListener.getInstance().raise(this, eventName, args);
return;
}
raiseEvent((BiConsumer) field.get(this), args);
}
@SuppressWarnings(NonWarning)
default void raiseEvent(BiConsumer event, TArgs args) {
require(args);
if (event == null) {
return;
}
event.accept((TSender) this, args);
}
}