Code cleanup and utility functions for plutolib
This commit is contained in:
parent
27c79917c5
commit
859a23cdc9
|
@ -0,0 +1,6 @@
|
|||
package cz.tefek.pluto;
|
||||
|
||||
public class Pluto
|
||||
{
|
||||
public static final boolean DEBUG_MODE = Boolean.valueOf(System.getProperty("cz.tefek.pluto.debug"));
|
||||
}
|
|
@ -1,25 +1,25 @@
|
|||
package cz.tefek.pluto.eventsystem.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.eventsystem.EventData;
|
||||
|
||||
@Retention(RUNTIME)
|
||||
@Target(ANNOTATION_TYPE)
|
||||
/**
|
||||
* @author 493msi
|
||||
*
|
||||
*/
|
||||
public @interface StaticPlutoEvent
|
||||
{
|
||||
/**
|
||||
* This actually does nothing. ¯\_(ツ)_/¯ Well, you can use it for improved
|
||||
* code readability.
|
||||
*
|
||||
*/
|
||||
Class<?> passingParamClass() default EventData.class;
|
||||
}
|
||||
package cz.tefek.pluto.eventsystem.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.eventsystem.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;
|
||||
}
|
||||
|
|
|
@ -1,228 +1,223 @@
|
|||
package cz.tefek.pluto.eventsystem.staticmode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import cz.tefek.pluto.eventsystem.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 @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<Class<? extends Annotation>, List<Method>>();
|
||||
private static List<Method> orphans = new ArrayList<Method>();
|
||||
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
eventRegistry.put(annotation, new ArrayList<Method>());
|
||||
|
||||
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<Method>();
|
||||
|
||||
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 (mostSuitableParam == null && parameter.isInstance(data))
|
||||
{
|
||||
mostSuitableParam = parameter;
|
||||
paramOut[i] = data;
|
||||
}
|
||||
|
||||
if (parameter.isInstance(data) && mostSuitableParam.isAssignableFrom(parameter))
|
||||
{
|
||||
mostSuitableParam = parameter;
|
||||
paramOut = new EventData[params.length];
|
||||
paramOut[i] = data;
|
||||
}
|
||||
}
|
||||
|
||||
if (mostSuitableParam != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
m.invoke(null, (Object[]) paramOut);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.logException(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();
|
||||
}
|
||||
}
|
||||
package cz.tefek.pluto.eventsystem.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.eventsystem.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 @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.logException(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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package cz.tefek.pluto.io.asl.resource;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
||||
/**
|
||||
* Doesn't do much right now. Just holds the default resource location.
|
||||
* Helper functions for {@link ResourceAddress}es.
|
||||
*
|
||||
* @author 493msi
|
||||
*/
|
||||
|
@ -9,4 +12,19 @@ public class ResourceHelper
|
|||
{
|
||||
public static final String GLOBAL_ROOT = "";
|
||||
public static final String DEFAULT_RESOURCE_ROOT = GLOBAL_ROOT + "data";
|
||||
|
||||
/**
|
||||
* Retrieves the size of the file denoted by {@link ResourceAddress}
|
||||
*
|
||||
* @param addr The input {@link ResourceAddress}
|
||||
*
|
||||
* @throws IOException On I/O errors.
|
||||
*
|
||||
* @return the file size
|
||||
* @since 0.3
|
||||
*/
|
||||
public static long fileSize(ResourceAddress addr) throws IOException
|
||||
{
|
||||
return Files.size(addr.toNIOPath());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue