package org.jdbi.v3.core.argument;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.jdbi.v3.core.argument.internal.MethodReturnValueNamedArgumentFinder;
import org.jdbi.v3.core.argument.internal.TypedValue;
import org.jdbi.v3.core.config.JdbiCache;
import org.jdbi.v3.core.config.JdbiCaches;
import org.jdbi.v3.core.qualifier.QualifiedType;
import org.jdbi.v3.core.qualifier.Qualifiers;
import org.jdbi.v3.core.statement.StatementContext;
public class ObjectMethodArguments extends MethodReturnValueNamedArgumentFinder {
private static final JdbiCache<Class<?>, Map<String, Method>> NULLARY_METHOD_CACHE =
JdbiCaches.declare(ObjectMethodArguments::load);
public ObjectMethodArguments(String prefix, Object object) {
super(prefix, object);
}
private static Map<String, Method> load(Class<?> type) {
if (Modifier.isPublic(type.getModifiers())) {
return Arrays.stream(type.getMethods())
.filter(m -> m.getParameterCount() == 0)
.collect(Collectors.toMap(Method::getName, Function.identity(), ObjectMethodArguments::bridgeMethodMerge));
} else {
final HashMap<String, Method> methodMap = new HashMap<>();
Optional.ofNullable(type.getSuperclass()).ifPresent(superclass -> methodMap.putAll(load(superclass)));
Arrays.stream(type.getInterfaces()).forEach(interfaceClass -> methodMap.putAll(load(interfaceClass)));
return methodMap;
}
}
@Override
protected Optional<TypedValue> getValue(String name, StatementContext ctx) {
Method method = NULLARY_METHOD_CACHE.get(obj.getClass(), ctx).get(name);
if (method == null) {
return Optional.empty();
}
QualifiedType<?> type = QualifiedType.of(method.getGenericReturnType())
.withAnnotations(ctx.getConfig(Qualifiers.class).findFor(method));
Object value = invokeMethod(method, ctx);
return Optional.of(new TypedValue(type, value));
}
@Override
protected NamedArgumentFinder getNestedArgumentFinder(Object obj) {
return new ObjectMethodArguments(null, obj);
}
@Override
public String toString() {
return "{lazy object functions arguments \"" + obj + "\"";
}
private static Method bridgeMethodMerge(Method a, Method b) {
return a.isBridge() ? b : a;
}
}