package org.sfm.jdbc.spring;

import org.sfm.jdbc.JdbcMapper;
import org.sfm.utils.ListHandler;
import org.sfm.utils.RowHandler;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.PreparedStatementCallback;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowMapper;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

/**
 * Provide integration point with Spring JdbcTemplate.
 * <p>
 * It implements {@link org.springframework.jdbc.core.RowMapper}, {@link org.springframework.jdbc.core.PreparedStatementCallback} and {@link org.springframework.jdbc.core.ResultSetExtractor}.
 * Because some JdbcTemplate template signature match against a few of those type you might need to downcast, declare the variable with a specific type or use the type specific method in {@link org.sfm.jdbc.spring.JdbcTemplateMapperFactory}.
 *
 * <p>
 *
 * <code>
 * class MyDao {
 * &nbsp;&nbsp;&nbsp;&nbsp;private final JdbcTemplateMapper&lt;DbObject&gt; mapper =
 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JdbcTemplateMapperFactory.newInstance().newMapper(DbObject.class);
 * &nbsp;&nbsp;&nbsp;&nbsp;private final RowMapper&lt;DbObject&gt; rowMapper = mapper;
 *
 * &nbsp;&nbsp;&nbsp;&nbsp;public void doSomething() {
 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&lt;DbObject&gt; results = template.query(DbHelper.TEST_DB_OBJECT_QUERY, rowMapper);
 * &nbsp;&nbsp;&nbsp;&nbsp;}
 *
 * &nbsp;&nbsp;&nbsp;&nbsp;public void doSomethingElse() {
 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;template
 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.query(TEST_DB_OBJECT_QUERY,
 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mapper.newResultSetExtractor((o) -&gt; System.out.println(o.toString())));
 * &nbsp;&nbsp;&nbsp;&nbsp;}
 * }
 *</code>
 *
 * @param <T> the mapped type
 * @see org.sfm.jdbc.JdbcMapperFactory
 * @see org.sfm.jdbc.JdbcMapper
 * @see org.sfm.jdbc.spring.JdbcTemplateMapperFactory#newPreparedStatementCallback(Class)
 * @see org.sfm.jdbc.spring.JdbcTemplateMapperFactory#newResultSetExtractor(Class)
 * @see org.sfm.jdbc.spring.JdbcTemplateMapperFactory#newRowMapper(Class)
 *
 */
public final class JdbcTemplateMapper<T> implements RowMapper<T>, PreparedStatementCallback<List<T>>, ResultSetExtractor<List<T>> {
	private final JdbcMapper<T> mapper;
	
	public JdbcTemplateMapper(JdbcMapper<T> mapper) {
		this.mapper = mapper;
	}

	@Override
	public T mapRow(ResultSet rs, int rowNum) throws SQLException {
		return mapper.map(rs);
	}

	@Override
	public List<T> doInPreparedStatement(PreparedStatement ps) throws SQLException,
			DataAccessException {
		ResultSet rs = ps.executeQuery();
		try {
			return extractData(rs);
		} finally {
			rs.close();
		}
	}

    @Override
    public List<T> extractData(ResultSet rs) throws SQLException,
            DataAccessException {
        return mapper.forEach(rs, new ListHandler<T>()).getList();
    }
	
	public <H extends RowHandler<T>> PreparedStatementCallback<H> newPreparedStatementCallback(final H handler) {
		return new PreparedStatementCallback<H>() {
			@Override
			public H doInPreparedStatement(
					PreparedStatement ps)
					throws SQLException, DataAccessException {
				ResultSet rs = ps.executeQuery();
				ResultSetExtractor<H> resultSetExtractor = newResultSetExtractor(handler);
				try {
					return resultSetExtractor.extractData(rs);
				} finally {
					rs.close();
				}
			}
		};
	}

	public <H extends RowHandler<T>>  ResultSetExtractor<H> newResultSetExtractor(final H handler) {
		return new ResultSetExtractor<H>() {
			@Override
			public H extractData(ResultSet rs) throws SQLException,
					DataAccessException {
				return mapper.forEach(rs, handler);
			}
		};
	}


}

@@ -999,16 +999,20 @@
  MyDao %7B
+%3Cbr%3E
 %0A * &nbs
@@ -1088,16 +1088,20 @@
 mapper =
+%3Cbr%3E
 %0A * &nbs
@@ -1210,16 +1210,20 @@
 .class);
+%3Cbr%3E
 %0A * &nbs
@@ -1301,19 +1301,27 @@
  mapper;
-%0A *
+%3Cbr%3E%0A *%3Cbr%3E
 %0A * &nbs
@@ -1363,24 +1363,28 @@
 omething() %7B
+%3Cbr%3E
 %0A * &nbsp;&n
@@ -1511,16 +1511,20 @@
 Mapper);
+%3Cbr%3E
 %0A * &nbs
@@ -1544,19 +1544,27 @@
 ;&nbsp;%7D
-%0A *
+%3Cbr%3E%0A *%3Cbr%3E
 %0A * &nbs
@@ -1614,16 +1614,20 @@
 Else() %7B
+%3Cbr%3E
 %0A * &nbs
@@ -1678,16 +1678,20 @@
 template
+%3Cbr%3E
 %0A * &nbs
@@ -1786,16 +1786,20 @@
 T_QUERY,
+%3Cbr%3E
 %0A * &nbs
@@ -1940,16 +1940,20 @@
 ng())));
+%3Cbr%3E
 %0A * &nbs
@@ -1977,13 +1977,21 @@
 sp;%7D
+%3Cbr%3E
 %0A * %7D
+%3Cbr%3E
 %0A *%3C

add br in javadoc