[PlutoLib] Removed cz.tefek.pluto.event.static

This commit is contained in:
493msi 2020-11-21 17:16:03 +01:00 committed by Tefek
parent cb613624a1
commit 262cba0000
4 changed files with 3 additions and 249 deletions

View File

@ -1,6 +1,8 @@
## 20.2.0.0-alpha.3 ## 20.2.0.0-alpha.3
* `[PlutoLib]` *Removed* `Severity`, use `SmartSeverity` instead * `[PlutoLib]` *Removed* `Severity`, use `SmartSeverity` instead
* `[PlutoLib]` *Removed* `TextIn`, `TextOut`, `ResourceImage` and `ResourceInputStream` * `[PlutoLib]` *Removed* `TextIn`, `TextOut`, `ResourceImage` and `ResourceInputStream`
* `[PlutoLib]` *Removed* `StaticPlutoEventManager` as the implementation was too obscure
* The module system now uses its own event management
* `[PlutoLib]` Made `OutputSplitStream` public as it is now reusable * `[PlutoLib]` Made `OutputSplitStream` public as it is now reusable
* `[PlutoLib]` Added the `@ConstantExpression` annotation * `[PlutoLib]` Added the `@ConstantExpression` annotation
* `[PlutoLib]` The `RAID#getIDOf` method now returns `OptionalInt` to avoid NPEs * `[PlutoLib]` The `RAID#getIDOf` method now returns `OptionalInt` to avoid NPEs
@ -61,4 +63,4 @@ can now only be modified only through public setters
* `[PlutoCore]` `[PlutoApplication]` now properly closes the `Logger` on exit * `[PlutoCore]` `[PlutoApplication]` now properly closes the `Logger` on exit
* `[PlutoLib]` Various typo fixes * `[PlutoLib]` Various typo fixes
* `[Pluto*]` Deprecated `Severity` for `SmartSeverity` and replaced all usages * `[Pluto*]` Deprecated `Severity` for `SmartSeverity` and replaced all usages
* `[Pluto*]` Deprecated `CRLF` with `LF` in all Java source files * `[Pluto*]` Replaced `CRLF` with `LF` in all Java source files

0
gradlew vendored Executable file → Normal file
View File

View File

@ -1,25 +0,0 @@
package cz.tefek.pluto.event.staticmode;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import cz.tefek.pluto.event.EventData;
/**
* @author 493msi
*
*/
@Retention(RUNTIME)
@Target(ANNOTATION_TYPE)
public @interface StaticPlutoEvent
{
/**
* This actually does nothing. ¯\_()_/¯ Well, you can use it for improved
* code readability.
*
*/
Class<?> passingParamClass() default EventData.class;
}

View File

@ -1,223 +0,0 @@
package cz.tefek.pluto.event.staticmode;
import java.util.*;
import java.util.Map.Entry;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import cz.tefek.pluto.event.EventData;
import cz.tefek.pluto.io.logger.Logger;
import cz.tefek.pluto.io.logger.SmartSeverity;
/**
* A universal event manager. Register an event {@link Annotation} of your
* choice (must be annotated with {@link StaticPlutoEvent &commat;Event}), then
* annotate some public static method and you are done! Now you can trigger the
* callbacks with ease. Multiple per-method events are possible! <i>Note that
* event callbacks require a data-passing parameter
* <tt>(extends {@link EventData})</tt>. The method will not be invoked
* otherwise!</i>
*
* @author 493msi
*
*/
public class StaticPlutoEventManager
{
private static Map<Class<? extends Annotation>, List<Method>> eventRegistry = new HashMap<>();
private static List<Method> orphans = new ArrayList<>();
public static void registerEventHandler(Class<?> clazz)
{
Method[] methods = clazz.getMethods();
int methodsFound = 0;
for (Method method : methods)
{
// The callback method must be static and public!
if (!(Modifier.isStatic(method.getModifiers()) && Modifier.isPublic(method.getModifiers())))
{
continue;
}
for (Annotation annotation : method.getDeclaredAnnotations())
{
if (annotation.annotationType().getAnnotation(StaticPlutoEvent.class) != null)
{
methodsFound++;
var parentAnnotation = eventRegistry.get(annotation.annotationType());
// Find a parent annotation.
if (parentAnnotation != null)
{
parentAnnotation.add(method);
}
// No parent annotation and fix for methods with 2+ event
// annotations.
else if (!orphans.contains(method))
{
orphans.add(method);
}
}
}
}
Logger.log(SmartSeverity.EVENT_PLUS, "Event handler " + clazz.getCanonicalName() + " scan found " + methodsFound + " method callback(s).");
}
public static void registerEvent(Class<? extends Annotation> annotation)
{
// @Event is necessary.
if (annotation.getAnnotation(StaticPlutoEvent.class) != null)
{
if (eventRegistry.containsKey(annotation))
{
Logger.log(SmartSeverity.EVENT_ERROR, "Annotation " + annotation.getCanonicalName() + " is already registered!");
return;
}
eventRegistry.put(annotation, new ArrayList<>());
Logger.log(SmartSeverity.EVENT_PLUS, "Event " + annotation.getCanonicalName() + " successfully registered!");
short retroactivelyFound = 0;
// Let's check all existing event Methods for this event.
for (Entry<Class<? extends Annotation>, List<Method>> entry : eventRegistry.entrySet())
{
// Checking the Method list for this event would make no
// sense.
if (annotation.equals(entry.getKey()))
{
continue;
}
for (Method method : entry.getValue())
{
// Just in case.
if (method.isAnnotationPresent(annotation))
{
eventRegistry.get(annotation).add(method);
retroactivelyFound++;
}
}
}
Logger.log(SmartSeverity.EVENT_PLUS, "Retroactive method checking found " + retroactivelyFound + " item(s).");
// Let's check the Method orphanage for some potential
// candidates.
short orphansFound = 0;
int orphansBefore = orphans.size();
List<Method> foundParents = new ArrayList<>();
for (Method method : orphans)
{
if (method.isAnnotationPresent(annotation))
{
foundParents.add(method);
// No duplicates.
if (!eventRegistry.get(annotation).contains(method))
{
eventRegistry.get(annotation).add(method);
orphansFound++;
}
}
}
orphans.removeAll(foundParents);
Logger.log(SmartSeverity.EVENT_PLUS, orphansFound + " orphan method(s) was/were bound and " + (orphansBefore - orphans.size()) + " removed from the storage!");
}
else
{
Logger.log(SmartSeverity.EVENT_ERROR, "Annotation " + annotation.getCanonicalName() + " is not annotated with @Event, can't register it.");
}
}
public static void fireEvent(Class<? extends Annotation> event, EventData data)
{
if (event.getAnnotation(StaticPlutoEvent.class) != null)
{
List<Method> methodList = eventRegistry.get(event);
if (methodList != null)
{
for (Method m : methodList)
{
// If a method contains more than one parameter, the most
// viable one will be chosen. Also, methods with no
// parameters are not valid.
Class<?>[] params = m.getParameterTypes();
Class<?> mostSuitableParam = null;
EventData[] paramOut = new EventData[params.length];
if (params.length == 0)
{
Logger.log(SmartSeverity.EVENT_WARNING, "Method " + m.toGenericString() + " has no parameters, will not be invoked by event!");
}
for (int i = 0; i < params.length; i++) {
Class<?> parameter = params[i];
if (!EventData.class.isAssignableFrom(parameter)) {
Logger.log(SmartSeverity.EVENT_ERROR, "Method " + m.toGenericString() + " contains invalid parameters. Only EventData instances are permitted.");
mostSuitableParam = null;
break;
}
if (parameter.isInstance(data))
{
if (mostSuitableParam == null)
{
mostSuitableParam = parameter;
paramOut[i] = data;
}
else if (mostSuitableParam.isAssignableFrom(parameter))
{
mostSuitableParam = parameter;
Arrays.fill(paramOut, 0, i, null);
paramOut[i] = data;
}
}
}
if (mostSuitableParam != null)
{
try
{
m.invoke(null, (Object[]) paramOut);
}
catch (Exception e)
{
Logger.log(e);
}
}
}
}
else
{
Logger.log(SmartSeverity.EVENT_ERROR, "There is no event like " + event.getCanonicalName() + " registered.");
}
}
else
{
Logger.log(SmartSeverity.EVENT_ERROR, event.getCanonicalName() + " is not an event!");
}
}
public static void unregisterAll()
{
eventRegistry.clear();
orphans.clear();
}
}