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

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;

import jp.co.cybec.cb3.accessor.AccessorsLifeCycle;
import jp.co.cybec.cb3.exception.AccessorAlreadyOpenedException;
import jp.co.cybec.cb3.exception.AccessorNotOpenException;
import jp.co.cybec.cb3.exception.DataFileIOException;
import jp.co.cybec.cb3.exception.DataFileNotFoundException;
import jp.co.cybec.cb3.exception.DataFormatException;
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;


/**
 * ファイルのレコード読み込みクラス。
 * @author Jianming Guo
 */
public class FlatFileRecordReaderImpl implements FlatFileRecordReader, AccessorsLifeCycle {
	/** ログ */
	private static final Log LOG = LogFactory.getLog(FlatFileRecordReaderImpl.class);

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

	/** ファイルパス */
	private String filepath = null;

	/** バッファーリーダー */
	private BufferedReader reader = null;

	/** ファイルのオープン状態を保持するフラグ */
	private boolean isOpen = false;

	/** エンコード */
	private String encode = null;

	/**
	 * ファイルをオープンします。
	 *
	 * @throws AccessorAlreadyOpenedException ファイルがすでにオープンされている場合に発生します。
	 * @throws DataFileNotFoundException ファイルが存在しない時に発生します。
	 * @throws DataFileIOException  レコードの読み込み時のIOエラーにより発生します。
	 */
	public void open() throws AccessorAlreadyOpenedException, DataFileNotFoundException, DataFileIOException {
		// すでにopenされている場合、例外をスローします。
		if (isOpen) {
			AccessorAlreadyOpenedException ex = new AccessorAlreadyOpenedException(MESSAGE
					.getErrorMessage(ErrorCodeConstant.ACCESSOR_FILEACCESS_FLAT_008,
							LogMessageConstant.CB3_ACCESSOR_FILEACCESS_002, filepath));
			LOG.info(ex.getMessage(), ex);
			throw ex;
		}

		// ファイルパスが設定されていない場合は例外をスローします。
		if (filepath == null || filepath.length() == 0) {
			DataFileNotFoundException ex = new DataFileNotFoundException(MESSAGE.getErrorMessage(
					ErrorCodeConstant.ACCESSOR_FILEACCESS_FLAT_016,
					LogMessageConstant.CB3_ACCESSOR_FILEACCESS_018));
			LOG.info(ex.getMessage(), ex);
			throw ex;
		}

		// ファイルのオープン処理
		try {
			reader = new BufferedReader(
					new InputStreamReader(new FileInputStream(new File(filepath)), encode));
			isOpen = true;
		} catch (FileNotFoundException e) {
			DataFileNotFoundException ex = new DataFileNotFoundException(MESSAGE.getErrorMessage(
					ErrorCodeConstant.ACCESSOR_FILEACCESS_FLAT_009,
					LogMessageConstant.CB3_ACCESSOR_FILEACCESS_003, e));
			LOG.info(ex.getMessage(), ex);
			throw ex;
		} catch (IOException e) {
			DataFileIOException ex = new DataFileIOException(MESSAGE.getErrorMessage(
					ErrorCodeConstant.ACCESSOR_FILEACCESS_FLAT_010,
					LogMessageConstant.CB3_ACCESSOR_FILEACCESS_004, e));
			LOG.info(ex.getMessage(), ex);
			throw ex;
		}
	}

	/**
	 * ファイルをオープンします。
	 *
	 * @param filepath データファイルのパス
	 * @throws AccessorAlreadyOpenedException ファイルがすでにオープンされている場合に発生します。
	 * @throws DataFileNotFoundException ファイルが存在しない時に発生します。
	 * @throws DataFileIOException  レコードの読み込み時のIOエラーにより発生します。
	 */
	public void open(String filepath) throws AccessorAlreadyOpenedException,
			DataFileNotFoundException, DataFileIOException {
		this.filepath = filepath;
		open();
	}

	/**
	 * 次のレコードを返却します
	 *
	 * @return 次のレコード
	 * @throws AccessorNotOpenException ファイルがオープンされていない場合に発生します。
	 * @throws DataFileIOException  レコードの読み込み時のIOエラーにより発生します。
	 * @throws DataFormatException レコード項目のフォーマットに失敗した場合に発生します。
	 */
	public FlatFileRecord nextRecord() throws AccessorNotOpenException, DataFileIOException, DataFormatException  {
		// 子クラスで実装
		return null;
	}

	/**
	 * ファイルをクローズします。
	 *
	 * @throws DataFileIOException ファイルのクローズに失敗した場合に発生します。
	 */
	public void close() throws DataFileIOException {
		if (isOpen) {
			// ファイルのクローズ処理
			try {
				reader.close();
				reader = null;
				isOpen = false;
			} catch (IOException e) {
				DataFileIOException ex = new DataFileIOException(MESSAGE.getErrorMessage(
						ErrorCodeConstant.ACCESSOR_FILEACCESS_FLAT_011,
						LogMessageConstant.CB3_ACCESSOR_FILEACCESS_004, e));
				LOG.info(ex.getMessage(), ex);
				throw ex;
			}
		}
	}

	/**
	 * 設定ファイルを読み込みます。
	 *
	 * @param key 設定ファイル名
	 */
	public void initialize(String key) {
		// 子クラスで実装
	}

	/**
	 * 後処理します。
	 */
	public void release() {
		close();
	}

	/**
	 * ファイルパスを返します。
	 *
	 * @return ファイルパス
	 */
	protected String getFilepath() {
		return filepath;
	}

	/**
	 * ファイルパスを設定します。
	 *
	 * @param filepath ファイルパス
	 */
	protected void setFilepath(String filepath) {
		this.filepath = filepath;
	}

	/**
	 * バッファーリーダーを返します。
	 *
	 * @return バッファーリーダー
	 */
	protected BufferedReader getBufferedReader() {
		return reader;
	}

	/**
	 * ファイルのオープン状態を返します。
	 *
	 * @return ファイルのオープン状態
	 */
	protected boolean isOpen() {
		return isOpen;
	}

	/**
	 * エンコードを返します。
	 *
	 * @return エンコード
	 */
	protected String getEncode() {
		return encode;
	}

	/**
	 * エンコードを設定します。
	 *
	 * @param encode エンコード
	 */
	protected void setEncode(String encode) {
		this.encode = encode;
	}
}
