diff --git a/plutolib/src/main/java/cz/tefek/pluto/Pluto.java b/plutolib/src/main/java/cz/tefek/pluto/Pluto.java new file mode 100644 index 0000000..77fc524 --- /dev/null +++ b/plutolib/src/main/java/cz/tefek/pluto/Pluto.java @@ -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")); +} diff --git a/plutolib/src/main/java/cz/tefek/pluto/eventsystem/staticmode/StaticPlutoEvent.java b/plutolib/src/main/java/cz/tefek/pluto/eventsystem/staticmode/StaticPlutoEvent.java index 4f498c4..2d31dc4 100644 --- a/plutolib/src/main/java/cz/tefek/pluto/eventsystem/staticmode/StaticPlutoEvent.java +++ b/plutolib/src/main/java/cz/tefek/pluto/eventsystem/staticmode/StaticPlutoEvent.java @@ -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; +} diff --git a/plutolib/src/main/java/cz/tefek/pluto/eventsystem/staticmode/StaticPlutoEventManager.java b/plutolib/src/main/java/cz/tefek/pluto/eventsystem/staticmode/StaticPlutoEventManager.java index 50670c4..f069754 100644 --- a/plutolib/src/main/java/cz/tefek/pluto/eventsystem/staticmode/StaticPlutoEventManager.java +++ b/plutolib/src/main/java/cz/tefek/pluto/eventsystem/staticmode/StaticPlutoEventManager.java @@ -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! Note that - * event callbacks require a data-passing parameter - * (extends {@link EventData}). The method will not be invoked - * otherwise! - * - * @author 493msi - * - */ -public class StaticPlutoEventManager -{ - private static Map, List> eventRegistry = new HashMap, List>(); - private static List 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 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()); - - 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, List> 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 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 event, EventData data) - { - if (event.getAnnotation(StaticPlutoEvent.class) != null) - { - List 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! Note that + * event callbacks require a data-passing parameter + * (extends {@link EventData}). The method will not be invoked + * otherwise! + * + * @author 493msi + * + */ +public class StaticPlutoEventManager +{ + private static Map, List> eventRegistry = new HashMap<>(); + private static List 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 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, List> 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 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 event, EventData data) + { + if (event.getAnnotation(StaticPlutoEvent.class) != null) + { + List 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(); + } +} diff --git a/plutolib/src/main/java/cz/tefek/pluto/io/asl/resource/ResourceHelper.java b/plutolib/src/main/java/cz/tefek/pluto/io/asl/resource/ResourceHelper.java index 818926d..f7e9b07 100644 --- a/plutolib/src/main/java/cz/tefek/pluto/io/asl/resource/ResourceHelper.java +++ b/plutolib/src/main/java/cz/tefek/pluto/io/asl/resource/ResourceHelper.java @@ -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()); + } }