package com.airbnb.epoxy;
import android.support.annotation.Nullable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Looks up a generated {@link ControllerHelper} implementation for a given adapter.
* If the adapter has no {@link com.airbnb.epoxy.AutoModel} models then a No-Op implementation will
* be returned.
*/
class ControllerHelperLookup {
private static final String GENERATED_HELPER_CLASS_SUFFIX = "_EpoxyHelper";
private static final Map<Class<?>, Constructor<?>> BINDINGS = new LinkedHashMap<>();
private static final NoOpControllerHelper NO_OP_CONTROLLER_HELPER = new NoOpControllerHelper();
static ControllerHelper getHelperForController(EpoxyController controller) {
Constructor<?> constructor = findConstructorForClass(controller.getClass());
if (constructor == null) {
return NO_OP_CONTROLLER_HELPER;
}
try {
return (ControllerHelper) constructor.newInstance(controller);
} catch (IllegalAccessException e) {
throw new RuntimeException("Unable to invoke " + constructor, e);
} catch (InstantiationException e) {
throw new RuntimeException("Unable to invoke " + constructor, e);
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
}
if (cause instanceof Error) {
throw (Error) cause;
}
throw new RuntimeException("Unable to get Epoxy helper class.", cause);
}
}
@Nullable
private static Constructor<?> findConstructorForClass(Class<?> controllerClass) {
Constructor<?> helperCtor = BINDINGS.get(controllerClass);
if (helperCtor != null || BINDINGS.containsKey(controllerClass)) {
return helperCtor;
}
String clsName = controllerClass.getName();
if (clsName.startsWith("android.") || clsName.startsWith("java.")) {
return null;
}
try {
Class<?> bindingClass = Class.forName(clsName + GENERATED_HELPER_CLASS_SUFFIX);
//noinspection unchecked
helperCtor = bindingClass.getConstructor(controllerClass);
} catch (ClassNotFoundException e) {
helperCtor = findConstructorForClass(controllerClass.getSuperclass());
} catch (NoSuchMethodException e) {
throw new RuntimeException("Unable to find Epoxy Helper constructor for " + clsName, e);
}
BINDINGS.put(controllerClass, helperCtor);
return helperCtor;
}
}