package com.github.czyzby.autumn.processor.impl; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.reflect.Method; import com.github.czyzby.autumn.annotation.Destroy; import com.github.czyzby.autumn.context.Context; import com.github.czyzby.autumn.context.ContextDestroyer; import com.github.czyzby.autumn.context.ContextInitializer; import com.github.czyzby.autumn.context.impl.method.MethodInvocation; import com.github.czyzby.autumn.context.impl.method.PrioritizedMethodInvocation; import com.github.czyzby.autumn.processor.AbstractAnnotationProcessor; import com.github.czyzby.kiwi.util.gdx.collection.GdxArrays; /** Invokes {@link Destroy}-annotated methods on context destruction. * * @author MJ */ public class DestroyAnnotationProcessor extends AbstractAnnotationProcessor<Destroy> { private final Array<PrioritizedMethodInvocation> methods = GdxArrays.newArray(); @Override public Class<Destroy> getSupportedAnnotationType() { return Destroy.class; } @Override public boolean isSupportingMethods() { return true; } @Override public void processMethod(final Method method, final Destroy annotation, final Object component, final Context context, final ContextInitializer initializer, final ContextDestroyer contextDestroyer) { methods.add(new PrioritizedMethodInvocation(method, component, MethodInvocation.getParametersFromContext(method.getParameterTypes(), context), annotation.priority())); } @Override public void doAfterScanning(final ContextInitializer initializer, final Context context, final ContextDestroyer destroyer) { methods.sort(); destroyer.addAction(new DestructionRunnable(methods)); } /** Invokes passed methods. Expects that the methods are already sorted. * * @author MJ */ public static class DestructionRunnable implements Runnable { private final Array<PrioritizedMethodInvocation> methods; public DestructionRunnable(final Array<PrioritizedMethodInvocation> methods) { this.methods = methods; } @Override public void run() { for (final PrioritizedMethodInvocation method : methods) { // We want to invoke all methods to make sure that all resources are closed, even if some fail - hence // try-catch. try { method.invoke(); } catch (final Exception exception) { if (Gdx.app != null) { Gdx.app.error("WARN", "Unable to invoke destruction method.", exception); } } } methods.clear(); } } }