package org.simpleflatmapper.jdbc.impl; import org.simpleflatmapper.jdbc.JdbcMapper; import org.simpleflatmapper.jdbc.JdbcMapperFactory; import org.simpleflatmapper.jdbc.QueryPreparer; import org.simpleflatmapper.jdbc.named.NamedSqlQuery; import java.lang.reflect.Type; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; public class SelectQueryWhereFactory<T> { private final String table; private final JdbcMapperFactory jdbcMapperFactory; private final JdbcMapper<T> jdbcMapper; private final ConcurrentMap<SelectQueryKey, SelectQueryImpl<T, ?>> cache = new ConcurrentHashMap<SelectQueryKey, SelectQueryImpl<T, ?>>(); public SelectQueryWhereFactory(String table, JdbcMapper<T> jdbcMapper, JdbcMapperFactory jdbcMapperFactory) { this.table = table; this.jdbcMapper = jdbcMapper; this.jdbcMapperFactory = jdbcMapperFactory; } @SuppressWarnings("unchecked") public <P> SelectQueryImpl<T, P> where(String whereClause, Type paramClass) { SelectQueryKey key = new SelectQueryKey(whereClause, paramClass); SelectQueryImpl<T, ?> selectQuery = cache.get(key); if (selectQuery == null) { SelectQueryImpl<T, P> newSelectQuery = newSelectQuery(whereClause, paramClass); selectQuery = cache.putIfAbsent(key, newSelectQuery); if (selectQuery == null) { selectQuery = newSelectQuery; } } return (SelectQueryImpl<T, P>) selectQuery; } private <P> SelectQueryImpl<T, P> newSelectQuery(String whereClause, Type paramClass) { String query = sqlQuery(whereClause); QueryPreparer<P> queryPreparer = jdbcMapperFactory.<P>from(paramClass).to(NamedSqlQuery.parse(query)); return new SelectQueryImpl<T, P>(queryPreparer, jdbcMapper); } private String sqlQuery(String whereClause) { return "SELECT * FROM " + table + " WHERE " + whereClause; } private static class SelectQueryKey { private final String query; private final Type type; private SelectQueryKey(String query, Type type) { this.query = query; this.type = type; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; SelectQueryKey that = (SelectQueryKey) o; if (!query.equals(that.query)) return false; return type.equals(that.type); } @Override public int hashCode() { int result = query.hashCode(); result = 31 * result + type.hashCode(); return result; } } }