package jp.co.areaweb.tools.csv;
import java.io.*;
import java.util.*;

/**
 * <p>CSVファイルを操作する。<br/>
 * このクラスではCSVに対するファイル操作と、各行を束ねた単位で操作します。各行は、CsvRecordオブジェクトで管理します。<br/>
 * このクラスは通常,CsvRecordクラスとセットで利用します。</p>
 * 
 * <p>
 *	<b>ファイルの読み出し例</b>:<br/>
 *	　　CsvFile csv = new CsvFile("C:\\Program Files\\data\\フォルダ\\ファイル.csv");<br/>
 *	　　csv.load();
 * </p>
 * <p>
 *	<b>CSVレコードの追加と変更</b>:<br/>
	　　if (csvf.isEmpty()) {<br/>
	　　　　// 新規レコード<br/>
	　　　　CsvRecord line = new CsvRecord();<br/>
	　　　　line.add("code");<br/>
	　　　　line.add("name");<br/>
	　　　　csvf.add(line);<br/>
	　　}<br/>
	　　else {<br/>
	　　　　// 既存タグ<br/>
	　　　　CsvRecord line = csvf.getFirst();<br/>
	　　　　line.set(1, "name");<br/>
	　　}<br/>
 * </p>
 * <p>
 *	<b>ファイルに保存</b>(上書き):<br/>
 *	　　csv.save();
 * </p>
 * 
 * @author y_hayashi
 * @version v2.17	2010/01/24
 * @see jp.co.areaweb.tools.csv.CsvRecord
 * @since 2005/06/01
 */
@SuppressWarnings("serial")
public class CsvFile extends LinkedList<CsvRecord> {
	//String pathname;		// 対象CSVファイルのパス名
	protected String charsetName = "Windows-31J";
	protected File file;
	protected LinkedList<CsvRecord> allRecords = new LinkedList<CsvRecord>();	// CSVファイル内の全データを保持するコレクション
	
	/**
	 * pathnameで指定されたパス名のファイルを対象のCSVファイルとします．
	 * @param pathname 対象のCSVファイルのパス名
	 */
	public CsvFile(String pathname) {
		this(new File(pathname));
	}

	/**
	 * fileで指定されたファイルを対象のCSVファイルとします．
	 * @param file 対象のCSVファイル
	 */
	public CsvFile(File file) {
		this.file = file;
	}
	
	/**
	 * CVSファイルからデータを読みだします。
	 */
	public void load() throws Exception {
		this.load(0);
	}
	
	/**
	 * CVSファイルからデータを読みだします。
	 * （読み出し数の制限付き）
	 */
	public void load(int limit) throws Exception {
		this.clear();
		LineNumberReader reader = new LineNumberReader(new InputStreamReader(new FileInputStream(this.file), this.charsetName));
		String line;
		for (int i = 0; ((limit <= 0) || (i < limit)); i++) {
			if ((line = reader.readLine()) == null) {
				break;
			}
			CsvRecord record = new CsvRecord();
			record.analizeRecord(line);
			this.add(record);
		}
		reader.close();
	}
	
	/**
	 * インポート元のキャラクタセットを設定する。
	 * デフォルトは、「Windows31J」
	 * @param charsetName 対象のCSVファイル内の文字コード
	 */
	public void setCharsetName(String charsetName) {
		this.charsetName = charsetName;
	}
	
	/**
	 * 現在設定されているCSVファイルの文字コードを取得する
	 * @return 現在設定されている文字コードを取得する
	 */
	public String getCharsetName() {
		return this.charsetName;
	}
	
	/**
	 * インポート元ファイルを取得する。
	 * @return 実体ファイル
	 */
	public File getFile() {
		return this.file;
	}

	/**
	 * 元ファイルを設定する。
	 * @return 実体ファイル
	 */
	public void setFile(File file) {
		this.file = file;
	}

	/**
	 * index番目の項目がdataStrになっているレコードを読み出す。
	 * @param index 検索対象とする列番号（０～）
	 * @param dataStr 検索値
	 * @return 条件に合致したレコード（複数）
	 */
	public CsvFile find(int index, String dataStr) {
		CsvFile result = new CsvFile(this.file);
		for (Iterator<CsvRecord> i = this.iterator(); i.hasNext(); ) {
			CsvRecord record = (CsvRecord)i.next();
			String data = (String)record.get(index);
			if (data.equals(dataStr)) {
				result.add(record);
			}
		}
		return result;
	}

	/**
	 * データ内容をファイルに書き戻す。<br>
	 * 当然、上書き書き込みになります。
	 * @throws IOException ファイルへの書き出しに失敗した。
	 */
	public void save() throws IOException {
		save(getFile());
	}

	/**
	 * データ内容をファイルに書き戻す。<br>
	 * @throws IOException ファイルへの書き出しに失敗した。
	 */
	public void save(File outputFile) throws IOException {
		FileOutputStream fo = new FileOutputStream(outputFile);
		PrintStream ps = new PrintStream(fo);
		for (Iterator<CsvRecord> i = this.iterator(); i.hasNext(); ) {
			CsvRecord record = (CsvRecord)i.next();
			ps.println(record.toString());
		}
		ps.close();
		fo.close();
	}
}
