package com.moparisthebest.jdbc; import java.lang.reflect.Method; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.*; public class ListQueryMapper extends QueryMapper { private static final InList defaultInList; static { InList def = null; try { final Class ensureContext = Class.forName(System.getProperty("QueryMapper.defaultInList.class", "com.moparisthebest.jdbc.BindInList")); final Method method = ensureContext.getMethod(System.getProperty("QueryMapper.defaultInList.method", "instance")); def = (InList) method.invoke(null); } catch (Throwable e) { // NEVER ignore throw new RuntimeException(e); } defaultInList = def; } protected final QueryMapper delegate; protected final InList inList; private static final String inListReplace = "{inList}"; private ListQueryMapper(Connection conn, String jndiName, QueryMapper delegate, ResultSetMapper cm, InList inList) { this.inList = inList; this.delegate = delegate == null ? new QueryMapper(conn, jndiName, cm) : (delegate instanceof ListQueryMapper ? ((ListQueryMapper)delegate).delegate : delegate); } public ListQueryMapper(QueryMapper delegate, InList inList) { this(null, null, delegate, null, inList); } public ListQueryMapper(QueryMapper delegate) { this(null, null, delegate, null, defaultInList); } public ListQueryMapper(Connection conn, InList inList) { this(conn, null, null, null, inList); } public ListQueryMapper(Connection conn, ResultSetMapper cm, InList inList) { this(conn, null, null, cm, inList); } public ListQueryMapper(Connection conn) { this(conn, defaultInList); } public ListQueryMapper(Connection conn, ResultSetMapper cm) { this(conn, cm, defaultInList); } public ListQueryMapper(String jndiName, InList inList) { this(null, jndiName, null, null, inList); } public ListQueryMapper(String jndiName, ResultSetMapper cm, InList inList) { this(null, jndiName, null, cm, inList); } public ListQueryMapper(String jndiName) { this(jndiName, defaultInList); } public ListQueryMapper(String jndiName, ResultSetMapper cm) { this(jndiName, cm, defaultInList); } public static ListQueryMapper wrap(final QueryMapper qm){ return qm instanceof ListQueryMapper ? (ListQueryMapper)qm : new ListQueryMapper(qm); } public static ListQueryMapper wrap(final QueryMapper qm, final InList inList){ return qm instanceof ListQueryMapper && ((ListQueryMapper)qm).inList == inList ? (ListQueryMapper)qm : new ListQueryMapper(qm, inList); } public InList.InListObject inList(final String columnName, final Collection values) throws SQLException { return this.inList.inList(delegate.conn, columnName, values); } // these update the database @Override public int executeUpdate(final PreparedStatement ps, final Object... bindObjects) throws SQLException { return delegate.executeUpdate(ps, bindObjects); } @Override public boolean executeUpdateSuccess(final PreparedStatement ps, final Object... bindObjects) throws SQLException { return delegate.executeUpdateSuccess(ps, bindObjects); } // these update the database using UpdateableDTOs @Override public int updateRows(final UpdateableDTO dto) throws SQLException { return delegate.updateRows(dto); } @Override public int updateRows(final Collection dtos) throws SQLException { return delegate.updateRows(dtos); } @Override public int updateRows(final UpdateableDTO[] dtos) throws SQLException { return delegate.updateRows(dtos); } @Override public int insertRows(final UpdateableDTO dto) throws SQLException { return delegate.insertRows(dto); } @Override public int insertRows(final Collection dtos) throws SQLException { return delegate.insertRows(dtos); } @Override public int insertRows(final UpdateableDTO[] dtos) throws SQLException { return delegate.insertRows(dtos); } // these grab ResultSets from the database @Override public ResultSet toResultSet(PreparedStatement ps, Object... bindObjects) throws SQLException { return delegate.toResultSet(ps, bindObjects); } // these are standard getters @Override public ResultSetMapper getCustomResultSetMapper() { return delegate.getCustomResultSetMapper(); } @Override public Connection getConnection() { return delegate.getConnection(); } // these just delegate and change no functionality @Override public void close() { delegate.close(); } // and these are standard @Override public boolean equals(final Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; final ListQueryMapper that = (ListQueryMapper) o; if (delegate != null ? !delegate.equals(that.delegate) : that.delegate != null) return false; if (inList != null ? !inList.equals(that.inList) : that.inList != null) return false; return true; } @Override public int hashCode() { int result = delegate != null ? delegate.hashCode() : 0; result = 31 * result + (inList != null ? inList.hashCode() : 0); return result; } @Override public String toString() { return "ListQueryMapper{" + "delegate=" + delegate + ", inList=" + inList + "} " + super.toString(); } // begin of ListQueryMapper specific methods private static StringBuilder recursiveReplace(final StringBuilder sb, final Object... bindObjects) { if (bindObjects != null && bindObjects.length > 0) { for (Object o : bindObjects) { if (o != null) { if (o instanceof InList.InListObject) { final int startIndex = sb.indexOf(inListReplace); if (startIndex < -1) return sb; // we've replaced all, maybe an error? meh sb.replace(startIndex, startIndex + inListReplace.length(), o.toString()); } else if (o instanceof Object[]) { recursiveReplace(sb, (Object[]) o); } else if (o instanceof Collection) { recursiveReplace(sb, ((Collection) o).toArray()); } } } } return sb; } protected String prepareSql(final String sql, final Object... bindObjects) { return !sql.contains(inListReplace) ? sql : recursiveReplace(new StringBuilder(sql), bindObjects).toString(); } @Override public int executeUpdate(final String sql, final Object... bindObjects) throws SQLException { return delegate.executeUpdate(prepareSql(sql, bindObjects), bindObjects); } @Override public boolean executeUpdateSuccess(final String sql, final Object... bindObjects) throws SQLException { return delegate.executeUpdateSuccess(prepareSql(sql, bindObjects), bindObjects); } @Override public ResultSet toResultSet(String sql, Object... bindObjects) throws SQLException { return delegate.toResultSet(prepareSql(sql, bindObjects), bindObjects); } // DO NOT EDIT BELOW THIS LINE, OR CHANGE THIS COMMENT, CODE AUTOMATICALLY GENERATED BY genQueryMapper.sh @Override public T toObject(PreparedStatement ps, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toObject(ps, componentType, bindObjects); } @Override public T toObject(String sql, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toObject(prepareSql(sql, bindObjects), componentType, bindObjects); } @Override public , V> Map toSingleMap(PreparedStatement ps, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toSingleMap(ps, componentType, mapValType, bindObjects); } @Override public , V> Map toSingleMap(String sql, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toSingleMap(prepareSql(sql, bindObjects), componentType, mapValType, bindObjects); } @Override public Map toSingleMap(PreparedStatement ps, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toSingleMap(ps, mapValType, bindObjects); } @Override public Map toSingleMap(String sql, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toSingleMap(prepareSql(sql, bindObjects), mapValType, bindObjects); } @Override public , E> T toCollection(PreparedStatement ps, final Class collectionType, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toCollection(ps, collectionType, componentType, bindObjects); } @Override public , E> T toCollection(String sql, final Class collectionType, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toCollection(prepareSql(sql, bindObjects), collectionType, componentType, bindObjects); } @Override public , E> T toCollection(PreparedStatement ps, T list, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toCollection(ps, list, componentType, bindObjects); } @Override public , E> T toCollection(String sql, T list, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toCollection(prepareSql(sql, bindObjects), list, componentType, bindObjects); } @Override public , K, E> T toMap(PreparedStatement ps, final Class returnType, Class mapKeyType, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toMap(ps, returnType, mapKeyType, componentType, bindObjects); } @Override public , K, E> T toMap(String sql, final Class returnType, Class mapKeyType, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toMap(prepareSql(sql, bindObjects), returnType, mapKeyType, componentType, bindObjects); } @Override public , K, E> T toMap(PreparedStatement ps, T map, Class mapKeyType, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toMap(ps, map, mapKeyType, componentType, bindObjects); } @Override public , K, E> T toMap(String sql, T map, Class mapKeyType, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toMap(prepareSql(sql, bindObjects), map, mapKeyType, componentType, bindObjects); } @Override public , K, E extends Collection, C> T toMapCollection(PreparedStatement ps, final Class returnType, Class mapKeyType, Class collectionType, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toMapCollection(ps, returnType, mapKeyType, collectionType, componentType, bindObjects); } @Override public , K, E extends Collection, C> T toMapCollection(String sql, final Class returnType, Class mapKeyType, Class collectionType, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toMapCollection(prepareSql(sql, bindObjects), returnType, mapKeyType, collectionType, componentType, bindObjects); } @Override public , K, E extends Collection, C> T toMapCollection(PreparedStatement ps, T map, Class mapKeyType, Class collectionType, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toMapCollection(ps, map, mapKeyType, collectionType, componentType, bindObjects); } @Override public , K, E extends Collection, C> T toMapCollection(String sql, T map, Class mapKeyType, Class collectionType, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toMapCollection(prepareSql(sql, bindObjects), map, mapKeyType, collectionType, componentType, bindObjects); } @Override public ListIterator toListIterator(PreparedStatement ps, final Class type, final Object... bindObjects) throws SQLException { return delegate.toListIterator(ps, type, bindObjects); } @Override public ListIterator toListIterator(String sql, final Class type, final Object... bindObjects) throws SQLException { return delegate.toListIterator(prepareSql(sql, bindObjects), type, bindObjects); } @Override public Iterator toIterator(PreparedStatement ps, final Class type, final Object... bindObjects) throws SQLException { return delegate.toIterator(ps, type, bindObjects); } @Override public Iterator toIterator(String sql, final Class type, final Object... bindObjects) throws SQLException { return delegate.toIterator(prepareSql(sql, bindObjects), type, bindObjects); } @Override public T[] toArray(PreparedStatement ps, final Class type, final Object... bindObjects) throws SQLException { return delegate.toArray(ps, type, bindObjects); } @Override public T[] toArray(String sql, final Class type, final Object... bindObjects) throws SQLException { return delegate.toArray(prepareSql(sql, bindObjects), type, bindObjects); } @Override public List toList(PreparedStatement ps, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toList(ps, componentType, bindObjects); } @Override public List toList(String sql, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toList(prepareSql(sql, bindObjects), componentType, bindObjects); } @Override public Map toMap(PreparedStatement ps, Class mapKeyType, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toMap(ps, mapKeyType, componentType, bindObjects); } @Override public Map toMap(String sql, Class mapKeyType, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toMap(prepareSql(sql, bindObjects), mapKeyType, componentType, bindObjects); } @Override public , C> Map toMapList(PreparedStatement ps, Class mapKeyType, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toMapList(ps, mapKeyType, componentType, bindObjects); } @Override public , C> Map toMapList(String sql, Class mapKeyType, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toMapList(prepareSql(sql, bindObjects), mapKeyType, componentType, bindObjects); } @Override public , E extends Map, V> T toCollectionMap(PreparedStatement ps, final Class collectionType, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toCollectionMap(ps, collectionType, componentType, mapValType, bindObjects); } @Override public , E extends Map, V> T toCollectionMap(String sql, final Class collectionType, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toCollectionMap(prepareSql(sql, bindObjects), collectionType, componentType, mapValType, bindObjects); } @Override public , E extends Map, V> T toCollectionMap(PreparedStatement ps, T list, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toCollectionMap(ps, list, componentType, mapValType, bindObjects); } @Override public , E extends Map, V> T toCollectionMap(String sql, T list, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toCollectionMap(prepareSql(sql, bindObjects), list, componentType, mapValType, bindObjects); } @Override public , K, E extends Map, V> T toMapMap(PreparedStatement ps, final Class returnType, Class mapKeyType, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapMap(ps, returnType, mapKeyType, componentType, mapValType, bindObjects); } @Override public , K, E extends Map, V> T toMapMap(String sql, final Class returnType, Class mapKeyType, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapMap(prepareSql(sql, bindObjects), returnType, mapKeyType, componentType, mapValType, bindObjects); } @Override public , K, E extends Map, V> T toMapMap(PreparedStatement ps, T map, Class mapKeyType, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapMap(ps, map, mapKeyType, componentType, mapValType, bindObjects); } @Override public , K, E extends Map, V> T toMapMap(String sql, T map, Class mapKeyType, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapMap(prepareSql(sql, bindObjects), map, mapKeyType, componentType, mapValType, bindObjects); } @Override public , K, C extends Collection, E extends Map, V> T toMapCollectionMap(PreparedStatement ps, final Class returnType, Class mapKeyType, Class collectionType, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapCollectionMap(ps, returnType, mapKeyType, collectionType, componentType, mapValType, bindObjects); } @Override public , K, C extends Collection, E extends Map, V> T toMapCollectionMap(String sql, final Class returnType, Class mapKeyType, Class collectionType, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapCollectionMap(prepareSql(sql, bindObjects), returnType, mapKeyType, collectionType, componentType, mapValType, bindObjects); } @Override public , K, C extends Collection, E extends Map, V> T toMapCollectionMap(PreparedStatement ps, T map, Class mapKeyType, Class collectionType, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapCollectionMap(ps, map, mapKeyType, collectionType, componentType, mapValType, bindObjects); } @Override public , K, C extends Collection, E extends Map, V> T toMapCollectionMap(String sql, T map, Class mapKeyType, Class collectionType, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapCollectionMap(prepareSql(sql, bindObjects), map, mapKeyType, collectionType, componentType, mapValType, bindObjects); } @Override public , V> ListIterator> toListIteratorMap(PreparedStatement ps, final Class type, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toListIteratorMap(ps, type, mapValType, bindObjects); } @Override public , V> ListIterator> toListIteratorMap(String sql, final Class type, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toListIteratorMap(prepareSql(sql, bindObjects), type, mapValType, bindObjects); } @Override public , V> Iterator> toIteratorMap(PreparedStatement ps, final Class type, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toIteratorMap(ps, type, mapValType, bindObjects); } @Override public , V> Iterator> toIteratorMap(String sql, final Class type, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toIteratorMap(prepareSql(sql, bindObjects), type, mapValType, bindObjects); } @Override public , V> Map[] toArrayMap(PreparedStatement ps, final Class type, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toArrayMap(ps, type, mapValType, bindObjects); } @Override public , V> Map[] toArrayMap(String sql, final Class type, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toArrayMap(prepareSql(sql, bindObjects), type, mapValType, bindObjects); } @Override public , V> List> toListMap(PreparedStatement ps, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toListMap(ps, componentType, mapValType, bindObjects); } @Override public , V> List> toListMap(String sql, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toListMap(prepareSql(sql, bindObjects), componentType, mapValType, bindObjects); } @Override public , V> Map> toMapMap(PreparedStatement ps, Class mapKeyType, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapMap(ps, mapKeyType, componentType, mapValType, bindObjects); } @Override public , V> Map> toMapMap(String sql, Class mapKeyType, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapMap(prepareSql(sql, bindObjects), mapKeyType, componentType, mapValType, bindObjects); } @Override public , V> Map>> toMapListMap(PreparedStatement ps, Class mapKeyType, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapListMap(ps, mapKeyType, componentType, mapValType, bindObjects); } @Override public , V> Map>> toMapListMap(String sql, Class mapKeyType, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapListMap(prepareSql(sql, bindObjects), mapKeyType, componentType, mapValType, bindObjects); } @Override public ListIterator> toListIteratorMap(PreparedStatement ps, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toListIteratorMap(ps, mapValType, bindObjects); } @Override public ListIterator> toListIteratorMap(String sql, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toListIteratorMap(prepareSql(sql, bindObjects), mapValType, bindObjects); } @Override public Iterator> toIteratorMap(PreparedStatement ps, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toIteratorMap(ps, mapValType, bindObjects); } @Override public Iterator> toIteratorMap(String sql, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toIteratorMap(prepareSql(sql, bindObjects), mapValType, bindObjects); } @Override public List> toListMap(PreparedStatement ps, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toListMap(ps, mapValType, bindObjects); } @Override public List> toListMap(String sql, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toListMap(prepareSql(sql, bindObjects), mapValType, bindObjects); } @Override public Map> toMapMap(PreparedStatement ps, Class mapKeyType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapMap(ps, mapKeyType, mapValType, bindObjects); } @Override public Map> toMapMap(String sql, Class mapKeyType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapMap(prepareSql(sql, bindObjects), mapKeyType, mapValType, bindObjects); } @Override public Map>> toMapListMap(PreparedStatement ps, Class mapKeyType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapListMap(ps, mapKeyType, mapValType, bindObjects); } @Override public Map>> toMapListMap(String sql, Class mapKeyType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapListMap(prepareSql(sql, bindObjects), mapKeyType, mapValType, bindObjects); } }