package com.github.czyzby.autumn.processor.impl;
import com.badlogic.gdx.utils.reflect.ClassReflection;
import com.badlogic.gdx.utils.reflect.Method;
import com.github.czyzby.autumn.annotation.Provider;
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.processor.AbstractAnnotationProcessor;
import com.github.czyzby.autumn.provider.DependencyProvider;
import com.github.czyzby.autumn.provider.impl.ReflectionDependencyProvider;
import com.github.czyzby.kiwi.util.gdx.reflection.Annotations;
/** Used to process {@link Provider} annotation. Registers providers in the context.
*
* @author MJ */
public class ProviderAnnotationProcessor extends AbstractAnnotationProcessor<Provider> {
@Override
public Class<Provider> getSupportedAnnotationType() {
return Provider.class;
}
@Override
public boolean isSupportingTypes() {
return true;
}
@Override
public void processType(final Class<?> type, final Provider annotation, final Object component,
final Context context, final ContextInitializer initializer, final ContextDestroyer contextDestroyer) {
if (component instanceof DependencyProvider<?>) {
context.addProvider((DependencyProvider<?>) component);
} else {
extractProviderMethods(component, context);
}
}
/** @param component will have its methods in class tree extracted.
* @param context will be used to resolve method dependencies. */
protected void extractProviderMethods(final Object component, final Context context) {
Class<?> componentClass = component.getClass();
while (componentClass != null && !componentClass.equals(Object.class)) {
final Method[] methods = ClassReflection.getDeclaredMethods(componentClass);
if (methods != null && methods.length > 0) {
convertToProviders(component, methods, context);
}
componentClass = componentClass.getSuperclass();
}
}
/** @param component is the owner of the methods.
* @param methods will be converted to dependency providers and added to context.
* @param context will contain the providers. Used to resolve methods' dependencies. */
protected void convertToProviders(final Object component, final Method[] methods, final Context context) {
for (final Method method : methods) {
final Class<?> returnType = method.getReturnType();
if (Annotations.isNotVoid(returnType)) { // Not null, void or Void.
context.addProvider(new ReflectionDependencyProvider(context, method, component));
}
}
}
}