/*
 * JdbcRecordReader.java
 * Copyright (C) 2008 Cyber Beans Corporation. All rights reserved.
 */
package jp.co.cybec.cb3.accessor.dbaccess;

import java.sql.ResultSet;
import java.sql.SQLException;

import jp.co.cybec.cb3.util.logging.ErrorCodeConstant;
import jp.co.cybec.cb3.util.logging.LogMessageConstant;
import jp.co.cybec.cb3.util.logging.LogMessageFactory;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator;

/**
 * データベース上のデータを１レコードずつ読み込むクラスです。<br>
 *
 * @author Lijuan Sun
 */
public class JdbcRecordReader implements DBRecordReader{

	/** ログ */
	private static final Log LOG = LogFactory.getLog(JdbcRecordReader.class);

	/** データ読み込み元のResultSet */
	private ResultSet resultSet = null;

	/** メッセージ */
	private static final LogMessageFactory MESSAGE = new LogMessageFactory(
			LogMessageConstant.CB3_MESSAGE_FILENAME);

	/** SQL */
	private String sql = null;

	/** SQLのパラメータ */
	private DBQueryParameterMap parameter = null;

	/** 処理中の行番号 */
	private int row = 0;

	/**
	 * コンストラクタ
	 *
	 * @param rs データ読み込み元のResultSet
	 * @param sql ResultSet取得に使用したSQL
	 * @param parameter ResultSet取得に使用したSQLの引数
	 */
	public JdbcRecordReader(ResultSet rs, String sql, DBQueryParameterMap parameter){

		this.resultSet = rs;
		this.sql = sql;
		this.parameter = parameter;
	};

	/**
	 * コンストラクタ
	 *
	 * @param rs データ読み込み元のResultSet
	 * @param sql ResultSet取得に使用したSQL
	 */
	public JdbcRecordReader(ResultSet rs, String sql){

		this(rs, sql, null);
	};

	/**
	 * 次のレコードを返却します
	 * @return 次のレコード。存在しない場合は、nullを返す。
	 * @throws DataAccessException 何らかのデータベースアクセスエラーが発生した場合。
	 */
	public DBRecord nextRecord() throws DataAccessException {

		JdbcRecord record = null;
		// 行番号をインクリメント。
		row++;

		try {
			if (resultSet.next()) {
				// 次のデータがある場合
				record = new JdbcRecord(resultSet, sql, parameter, row);

				// デバッグログ
				if (LOG.isDebugEnabled()) {
					LOG.debug(MESSAGE.getMessage(LogMessageConstant.CB3_ACCESSOR_DBACCESS_015, row, record.toMap()));
				}
			}
			else {
				// 次のデータがない場合
				record = null;
			}
		} catch (SQLException e) {
			// DataAccessExceptionをスローする;
			String stringOfParameter = (parameter == null ? "" : parameter.toString());
			DataAccessException ex = new SQLStateSQLExceptionTranslator().translate(MESSAGE
					.getErrorMessage(ErrorCodeConstant.ACCESSOR_DBACCESS_030,
							LogMessageConstant.CB3_ACCESSOR_DBACCESS_004, sql, stringOfParameter,
							row), "", e);
			// infoでログを出力する
			LOG.info(ex.getMessage(), ex);
			// スローする
			throw ex;
		}
		// 結果を戻す
		return record;
	}
}
