package org.jdbi.v3.core.argument;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
import net.jodah.expiringmap.ExpirationPolicy;
import net.jodah.expiringmap.ExpiringMap;
import org.jdbi.v3.core.statement.StatementContext;
public class ObjectMethodArguments extends MethodReturnValueNamedArgumentFinder {
private static final Map<Class<?>, Map<String, Method>> CLASS_METHODS = ExpiringMap.builder()
.expiration(10, TimeUnit.MINUTES)
.expirationPolicy(ExpirationPolicy.ACCESSED)
.entryLoader((Class<?> type) ->
Arrays.stream(type.getMethods())
.filter(m -> m.getParameterCount() == 0)
.collect(Collectors.toMap(Method::getName, Function.identity(), ObjectMethodArguments::bridgeMethodMerge)))
.build();
private final Map<String, Method> methods;
public ObjectMethodArguments(String prefix, Object object) {
super(prefix, object);
this.methods = CLASS_METHODS.get(object.getClass());
}
@Override
Optional<TypedValue> getValue(String name, StatementContext ctx) {
Method method = methods.get(name);
if (method == null) {
return Optional.empty();
}
Type type = method.getGenericReturnType();
Object value = invokeMethod(method, ctx);
return Optional.of(new TypedValue(type, value));
}
@Override
NamedArgumentFinder getNestedArgumentFinder(Object obj) {
return new ObjectMethodArguments(null, obj);
}
@Override
public String toString() {
return "{lazy object functions arguments \"" + object + "\"";
}
private static Method bridgeMethodMerge(Method a, Method b) {
return (a.isBridge()) ? b : a;
}
}