package org.jdbi.v3.core.argument;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Stream;
import net.jodah.expiringmap.ExpirationPolicy;
import net.jodah.expiringmap.ExpiringMap;
import org.jdbi.v3.core.statement.StatementContext;
import org.jdbi.v3.core.statement.UnableToCreateStatementException;
import static java.util.stream.Collectors.toMap;
public class ObjectFieldArguments extends ObjectPropertyNamedArgumentFinder {
private static final Map<Class<?>, Map<String, Field>> CLASS_FIELDS = ExpiringMap.builder()
.expiration(10, TimeUnit.MINUTES)
.expirationPolicy(ExpirationPolicy.ACCESSED)
.entryLoader((Class<?> type) ->
Stream.of(type.getFields())
.collect(toMap(Field::getName, Function.identity())))
.build();
private final Map<String, Field> fields;
public ObjectFieldArguments(String prefix, Object bean) {
super(prefix, bean);
this.fields = CLASS_FIELDS.get(bean.getClass());
}
@Override
Optional<TypedValue> getValue(String name, StatementContext ctx) {
Field field = fields.get(name);
if (field == null) {
return Optional.empty();
}
try {
Type type = field.getGenericType();
Object value = field.get(object);
return Optional.of(new TypedValue(type, value));
} catch (IllegalAccessException e) {
throw new UnableToCreateStatementException(String.format("Access exception getting field for "
+ "bean property [%s] on [%s]",
name, object), e, ctx);
}
}
@Override
NamedArgumentFinder getNestedArgumentFinder(Object obj) {
return new ObjectFieldArguments(null, obj);
}
@Override
public String toString() {
return "{lazy bean field arguments \"" + object + "\"";
}
}