Intial commit

This commit is contained in:
Willem Cazander 2023-09-24 12:41:43 +02:00
parent 7329fb8dea
commit 73f201bdac
268 changed files with 11220 additions and 5 deletions

10
no2all-react/pom.xml Normal file
View file

@ -0,0 +1,10 @@
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>love.distributedrebirth.no2all</groupId>
<artifactId>no2all</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>no2all-react</artifactId>
<name>No2All-React</name>
</project>

View file

@ -0,0 +1,17 @@
package love.distributedrebirth.no2all.react;
public interface No2AllReact {
void claim(No2AllReactSlot slot);
void claimIn(No2AllReactSlot slot, Class<?> eventType);
void claimOut(No2AllReactSlot slot, Class<?> eventType);
void requireSlot(No2AllReactSlot slot, No2AllReactSlot dep);
void requireService(No2AllReactSlot slot, Class<?> serviceType);
void fire(No2AllReactSlot slot, Object event);
void fireForEach(No2AllReactSlot slot, Object event);
<T> void registrate(No2AllReactSlot slot, Class<T> eventType, No2AllReactListener<T> listener);
<T> T service(Class<T> serviceType);
void release(No2AllReactSlot slot);
}

View file

@ -0,0 +1,7 @@
package love.distributedrebirth.no2all.react;
@FunctionalInterface
public interface No2AllReactListener<T> {
void onEvent(No2AllReactSlotSignal<T> signal);
}

View file

@ -0,0 +1,75 @@
package love.distributedrebirth.no2all.react;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public final class No2AllReactSlot {
private final No2AllReactSlot parent;
private final String slotSlug;
private final String slotPath;
private No2AllReactSlot(No2AllReactSlot parent, String slotSlug) {
this.parent = parent;
this.slotSlug = slotSlug;
this.slotPath = createSlotPath();
}
public No2AllReactSlot getParent() {
return parent;
}
public String getSlotSlug() {
return slotSlug;
}
public String getSlotPath() {
return slotPath;
}
public String createSlotPath() {
List<String> slugs = new ArrayList<>();
No2AllReactSlot parentNode = this;
while (parentNode != null) {
slugs.add(parentNode.getSlotSlug());
parentNode = parentNode.getParent();
}
StringBuilder buf = new StringBuilder();
for (int i = slugs.size() - 1; i >= 0; i--) {
buf.append(slugs.get(i));
if (i > 0) {
buf.append(',');
}
}
return buf.toString();
}
@Override
public int hashCode() {
return Objects.hash(slotPath);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
No2AllReactSlot other = (No2AllReactSlot) obj;
return Objects.equals(slotPath, other.slotPath);
}
public static No2AllReactSlot ofClass(Class<?> scriptClz) {
return new No2AllReactSlot(null, scriptClz.getPackageName() + ":type=" + scriptClz.getSimpleName());
}
public static No2AllReactSlot of(No2AllReactSlot parent, String kvPair) {
return new No2AllReactSlot(parent, kvPair);
}
}

View file

@ -0,0 +1,7 @@
package love.distributedrebirth.no2all.react;
public final class No2AllReactSlotLoad {
public No2AllReactSlotLoad() {
}
}

View file

@ -0,0 +1,30 @@
package love.distributedrebirth.no2all.react;
public final class No2AllReactSlotSignal<T> {
private final No2AllReactSlot target;
private final T data;
private final No2AllReact react;
public No2AllReactSlotSignal(No2AllReactSlot target, T data, No2AllReact react) {
this.target = target;
this.data = data;
this.react = react;
}
public No2AllReactSlot getTarget() {
return target;
}
public T getData() {
return data;
}
public No2AllReact getReact() {
return react;
}
// public T $() {
// return getData();
// }
}

View file

@ -0,0 +1,7 @@
package love.distributedrebirth.no2all.react;
public interface No2AllReactTypeScript extends No2AllReactListener<No2AllReactSlotLoad> {
default void onRelease(No2AllReactSlotSignal<No2AllReactSlotLoad> signal) {
}
}

View file

@ -0,0 +1,16 @@
package love.distributedrebirth.no2all.react.warp;
import love.distributedrebirth.no2all.react.No2AllReactSlot;
public abstract class No2AllActAbstractSlot {
private final No2AllReactSlot slot;
public No2AllActAbstractSlot(No2AllReactSlot slot) {
this.slot = slot;
}
public final No2AllReactSlot getSlot() {
return slot;
}
}

View file

@ -0,0 +1,10 @@
package love.distributedrebirth.no2all.react.warp;
import love.distributedrebirth.no2all.react.No2AllReactSlot;
public final class No2AllArtWarpSlotAdd extends No2AllActAbstractSlot {
protected No2AllArtWarpSlotAdd(No2AllReactSlot slot) {
super(slot);
}
}

View file

@ -0,0 +1,10 @@
package love.distributedrebirth.no2all.react.warp;
import love.distributedrebirth.no2all.react.No2AllReactSlot;
public final class No2AllArtWarpSlotRemove extends No2AllActAbstractSlot {
protected No2AllArtWarpSlotRemove(No2AllReactSlot slot) {
super(slot);
}
}

View file

@ -0,0 +1,29 @@
package love.distributedrebirth.no2all.react.warp;
import java.util.ArrayList;
import java.util.List;
import love.distributedrebirth.no2all.react.No2AllReactSlot;
public class No2AllReactSlotContract {
private final No2AllReactSlot slot;
final List<Class<?>> slotTypesIn = new ArrayList<>();
final List<Class<?>> slotTypesOut = new ArrayList<>();
public No2AllReactSlotContract(No2AllReactSlot slot) {
this.slot = slot;
}
public No2AllReactSlot getSlot() {
return slot;
}
public List<Class<?>> getSlotTypesIn() {
return slotTypesIn;
}
public List<Class<?>> getSlotTypesOut() {
return slotTypesOut;
}
}

View file

@ -0,0 +1,184 @@
package love.distributedrebirth.no2all.react.warp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import love.distributedrebirth.no2all.react.No2AllReactSlotLoad;
import love.distributedrebirth.no2all.react.No2AllReact;
import love.distributedrebirth.no2all.react.No2AllReactListener;
import love.distributedrebirth.no2all.react.No2AllReactSlot;
import love.distributedrebirth.no2all.react.No2AllReactSlotSignal;
import love.distributedrebirth.no2all.react.No2AllReactTypeScript;
public class No2AllReactWarpCore implements No2AllReact {
public static final No2AllReactSlot DILITHIUM = No2AllReactSlot.ofClass(No2AllReactWarpCore.class);
private final Map<No2AllReactSlot, No2AllReactWarpFuel> slots = new HashMap<>();
private final Map<Class<?>, Object> services = new HashMap<>();
private final List<BacklogEvent> backlog = new ArrayList<>();
private Object currentEvent = null;
public No2AllReactWarpCore() {
claim(DILITHIUM);
toWarpFuel(DILITHIUM).registrateTypeIn(No2AllReactSlotLoad.class);
toWarpFuel(DILITHIUM).registrateTypeOut(No2AllArtWarpSlotAdd.class);
toWarpFuel(DILITHIUM).registrateTypeOut(No2AllArtWarpSlotRemove.class);
}
public void load(No2AllReactTypeScript script) {
Objects.requireNonNull(script).onEvent(new No2AllReactSlotSignal<>(DILITHIUM, new No2AllReactSlotLoad(), this));
}
public No2AllReactSlotContract getSlotContract(No2AllReactSlot slot) {
return toWarpFuel(slot).readContract();
}
public List<No2AllReactSlot> listChilds(No2AllReactSlot slot) {
Objects.requireNonNull(slot);
List<No2AllReactSlot> result = new ArrayList<>();
synchronized (slots) {
for (No2AllReactSlot slug : slots.keySet()) {
if (slot == null) {
result.add(slug);
continue;
}
if (slug.getParent() == null) {
continue;
}
if (slug.getParent().getSlotPath().equals(slot.getSlotPath())) {
result.add(slug);
}
}
}
return result;
}
@Override
public void fireForEach(No2AllReactSlot slot, Object event) {
for (No2AllReactSlot target : listChilds(slot)) {
fire(target, event);
}
}
@Override
public void fire(No2AllReactSlot slot, Object event) {
Objects.requireNonNull(slot);
Objects.requireNonNull(event);
if (currentEvent != null) {
backlog.add(new BacklogEvent(slot, event));
return;
}
currentEvent = event;
try {
toWarpFuel(slot).fire(event, slot);
List<BacklogEvent> backlog2 = new ArrayList<>(backlog);
backlog.clear();
for (BacklogEvent next : backlog2) {
toWarpFuel(next.slot).fire(next.event, next.slot);
}
} finally {
currentEvent = null;
}
}
static class BacklogEvent {
No2AllReactSlot slot;
Object event;
public BacklogEvent(No2AllReactSlot slot, Object event) {
this.slot = slot;
this.event = event;
}
}
@SuppressWarnings("unchecked")
@Override
public <T> void registrate(No2AllReactSlot slot, Class<T> eventType, No2AllReactListener<T> listener) {
No2AllReactListener<Object> listenerObj = (No2AllReactListener<Object>) listener;
toWarpFuel(slot).registrateListener(eventType, listenerObj);
}
@Override
public void release(No2AllReactSlot slot) {
toWarpFuel(slot).removeAll();
synchronized (slots) {
slots.remove(slot);
}
fire(DILITHIUM, new No2AllArtWarpSlotRemove(slot));
}
@Override
public void claim(No2AllReactSlot slot) {
Objects.requireNonNull(slot);
synchronized (slots) {
if (slots.keySet().contains(slot)) {
throw new IllegalStateException("Slug already claimed: " + slot.getSlotPath());
}
slots.put(slot, new No2AllReactWarpFuel(this, slot));
}
fire(DILITHIUM, new No2AllArtWarpSlotAdd(slot));
}
@Override
public void claimOut(No2AllReactSlot slot, Class<?> eventType) {
toWarpFuel(slot).registrateTypeOut(eventType);
}
@Override
public void claimIn(No2AllReactSlot slot, Class<?> eventType) {
toWarpFuel(slot).registrateTypeIn(eventType);
}
@Override
public void requireSlot(No2AllReactSlot slot, No2AllReactSlot dep) {
if (!isClaimed(dep)) {
throw new IllegalStateException("Script dependency missing: " + dep);
}
toWarpFuel(slot).addRequireSlot(dep);
}
@Override
public void requireService(No2AllReactSlot slot, Class<?> serviceType) {
toWarpFuel(slot).addRequireService(serviceType);
}
@SuppressWarnings("unchecked")
@Override
public <T> T service(Class<T> serviceType) {
Objects.requireNonNull(serviceType);
synchronized (services) {
return (T) services.get(serviceType);
}
}
public <T> void addService(Class<T> serviceType, T service) {
Objects.requireNonNull(serviceType);
Objects.requireNonNull(service);
synchronized (services) {
services.put(serviceType, service);
}
}
public boolean isClaimed(No2AllReactSlot slug) {
Objects.requireNonNull(slug);
synchronized (slots) {
return slots.keySet().contains(slug);
}
}
protected No2AllReactWarpFuel toWarpFuel(No2AllReactSlot slot) {
Objects.requireNonNull(slot);
No2AllReactWarpFuel result;
synchronized (slots) {
result = slots.get(slot);
if (result == null) {
throw new IllegalStateException("Slot not claimed: " + slot.getSlotPath());
}
}
return result;
}
}

View file

@ -0,0 +1,120 @@
package love.distributedrebirth.no2all.react.warp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import love.distributedrebirth.no2all.react.No2AllReactListener;
import love.distributedrebirth.no2all.react.No2AllReactSlot;
import love.distributedrebirth.no2all.react.No2AllReactSlotSignal;
public class No2AllReactWarpFuel {
private final No2AllReactWarpCore no2AllReactWarpCore;
private final No2AllReactSlot containerSlot;
private final Map<Class<?>, List<No2AllReactListener<Object>>> listeners = new HashMap<>();
private final Set<Class<?>> claimTypesOut = new HashSet<>();
private final Set<Class<?>> claimTypesIn = new HashSet<>();
private final Set<Class<?>> requireServices = new HashSet<>();
private final Set<No2AllReactSlot> requireSlots = new HashSet<>();
protected No2AllReactWarpFuel(No2AllReactWarpCore no2AllReactWarpCore, No2AllReactSlot containerSlot) {
this.no2AllReactWarpCore = Objects.requireNonNull(no2AllReactWarpCore);
this.containerSlot = Objects.requireNonNull(containerSlot);
}
private List<No2AllReactListener<Object>> toViewOfListeners(Class<?> eventType) {
List<No2AllReactListener<Object>> result = new ArrayList<>();
synchronized (listeners) {
List<No2AllReactListener<Object>> typeListeners = listeners.get(eventType);
if (typeListeners == null) {
return result;
}
result.addAll(typeListeners);
}
return result;
}
public void fire(Object event, No2AllReactSlot slot) {
for (No2AllReactListener<Object> listener : toViewOfListeners(event.getClass())) {
listener.onEvent(new No2AllReactSlotSignal<>(slot, event, this.no2AllReactWarpCore));
}
}
public void registrateListener(Class<?> eventType, No2AllReactListener<Object> listener) {
Objects.requireNonNull(eventType);
Objects.requireNonNull(listener);
synchronized (listeners) {
List<No2AllReactListener<Object>> typeListeners = listeners.get(eventType);
if (typeListeners == null) {
typeListeners = new ArrayList<>();
listeners.put(eventType, typeListeners);
}
typeListeners.add(listener);
}
}
public void registrateTypeOut(Class<?> eventType) {
Objects.requireNonNull(eventType);
synchronized (claimTypesOut) {
claimTypesOut.add(eventType);
}
}
public void registrateTypeIn(Class<?> eventType) {
Objects.requireNonNull(eventType);
synchronized (claimTypesIn) {
claimTypesIn.add(eventType);
}
}
public No2AllReactSlotContract readContract() {
No2AllReactSlotContract result = new No2AllReactSlotContract(containerSlot);
synchronized (claimTypesIn) {
result.slotTypesIn.addAll(claimTypesIn);
}
synchronized (claimTypesOut) {
result.slotTypesOut.addAll(claimTypesOut);
}
return result;
}
public void addRequireService(Class<?> serviceType) {
Objects.requireNonNull(serviceType);
synchronized (requireServices) {
requireServices.add(serviceType);
}
}
public void addRequireSlot(No2AllReactSlot dep) {
Objects.requireNonNull(dep);
synchronized (requireSlots) {
requireSlots.add(dep);
}
}
public void removeAll() {
synchronized (listeners) {
for (Class<?> eventType : listeners.keySet()) {
List<No2AllReactListener<Object>> typeListeners = listeners.get(eventType);
typeListeners.clear();
}
}
synchronized (claimTypesOut) {
claimTypesOut.clear();
}
synchronized (claimTypesIn) {
claimTypesIn.clear();
}
synchronized (requireServices) {
requireServices.clear();
}
synchronized (requireSlots) {
requireSlots.clear();
}
}
}

View file

@ -0,0 +1,30 @@
package love.distributedrebirth.no2all.react.warp;
import love.distributedrebirth.no2all.react.No2AllReactSlotLoad;
import java.util.logging.Logger;
import love.distributedrebirth.no2all.react.No2AllReact;
import love.distributedrebirth.no2all.react.No2AllReactSlot;
import love.distributedrebirth.no2all.react.No2AllReactSlotSignal;
import love.distributedrebirth.no2all.react.No2AllReactTypeScript;
public class No2AllRtsWarpSpeedMonitor implements No2AllReactTypeScript {
public static final No2AllReactSlot API = No2AllReactSlot.ofClass(No2AllRtsWarpSpeedMonitor.class);
private static final No2AllReactSlot API_DILITHIUM = No2AllReactWarpCore.DILITHIUM;
private static final Logger LOG = Logger.getLogger(No2AllRtsWarpSpeedMonitor.class.getName());
@Override
public void onEvent(No2AllReactSlotSignal<No2AllReactSlotLoad> signal) {
No2AllReact react = signal.getReact();
react.claim(API);
react.requireSlot(API, API_DILITHIUM);
react.registrate(API_DILITHIUM, No2AllArtWarpSlotAdd.class, v -> {
LOG.fine("slot-add: " + v.getData().getSlot().getSlotPath());
});
react.registrate(API_DILITHIUM, No2AllArtWarpSlotRemove.class, v -> {
LOG.fine("slot-remove: " + v.getData().getSlot().getSlotPath());
});
}
}