package org.simpleflatmapper.jdbi3;
import org.jdbi.v3.core.config.ConfigRegistry;
import org.jdbi.v3.core.mapper.RowMapper;
import org.jdbi.v3.core.mapper.RowMapperFactory;
import org.simpleflatmapper.jdbc.DynamicJdbcMapper;
import org.simpleflatmapper.jdbc.JdbcMapperFactory;
import org.simpleflatmapper.map.Mapper;
import org.simpleflatmapper.util.BiPredicate;
import org.simpleflatmapper.util.UnaryFactory;
import java.lang.reflect.Type;
import java.sql.ResultSet;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public class SfmRowMapperFactory implements RowMapperFactory {
private static final UnaryFactory<Type, Mapper<ResultSet, ?>> DEFAULT_FACTORY = new UnaryFactory<Type, Mapper<ResultSet, ?>>() {
@Override
public Mapper<ResultSet, ?> newInstance(Type type) {
return JdbcMapperFactory.newInstance().newMapper(type);
}
};
private static final BiPredicate<Type, ConfigRegistry> DEFAULT_ACCEPT_PREDICATE = new BiPredicate<Type, ConfigRegistry>() {
@Override
public boolean test(Type type, ConfigRegistry configRegistry) {
return true;
}
};
private final UnaryFactory<Type, Mapper<ResultSet, ?>> mapperFactory;
private final ConcurrentMap<Type, RowMapper<?>> cache = new ConcurrentHashMap<Type, RowMapper<?>>();
private final BiPredicate<Type, ConfigRegistry> acceptsPredicate;
public SfmRowMapperFactory() {
this(DEFAULT_FACTORY);
}
public SfmRowMapperFactory(UnaryFactory<Type, Mapper<ResultSet, ?>> mapperFactory) {
this(DEFAULT_ACCEPT_PREDICATE, mapperFactory);
}
public SfmRowMapperFactory(BiPredicate<Type, ConfigRegistry> acceptsPredicate, UnaryFactory<Type, Mapper<ResultSet, ?>> mapperFactory) {
this.mapperFactory = mapperFactory;
this.acceptsPredicate = acceptsPredicate;
}
private <T> RowMapper<T> toRowMapper(Mapper<ResultSet, T> resultSetMapper) {
RowMapper<T> mapper;
if (resultSetMapper instanceof DynamicJdbcMapper) {
mapper = new DynamicRowMapper<T>((DynamicJdbcMapper<T>) resultSetMapper);
} else {
mapper = new StaticRowMapper<T>(resultSetMapper);
}
return mapper;
}
@Override
public Optional<RowMapper<?>> build(Type type, ConfigRegistry configRegistry) {
if (acceptsPredicate.test(type, configRegistry)) {
RowMapper<?> rowMapper = cache.get(type);
if (rowMapper == null) {
Mapper<ResultSet, ?> resultSetMapper = mapperFactory.newInstance(type);
rowMapper = toRowMapper(resultSetMapper);
RowMapper<?> cachedMapper = cache.putIfAbsent(type, rowMapper);
if (cachedMapper != null) {
rowMapper = cachedMapper;
}
}
return Optional.of(rowMapper);
}
return Optional.empty();
}
}