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

/**
 * CSVファイルの１行分のレコードを表す.<br/>
 * １行は、Stringオブジェクトのコレクションとして表現する.<br/>
 * このクラスは通常,CsvFileクラスとセットで利用します.<br/>
 * 利用方法につては、CsvFileクラスのコメントを参照してください。<br/>
 *
 * @author y_hayashi
 * @version v2.17	2010/01/24
 * @see jp.co.areaweb.tools.csv.CsvFile
 * @since 2005/06/01
 */
@SuppressWarnings("serial")
public class CsvRecord extends LinkedList<String>
{
	/**
	 * lineで示された文字列を、CSVレコードとして構文解析を行い、自身に取り込む.
	 * 取り込まれたセル文字列は、自信(LinkedList)のアイテムとして格納されます.
	 * 格納順序は、左から順に格納される.
	 * v2.17-2010/01/24より、ダブルクォーテーションで囲まれたセルを処理できるように変更しました。
	 * 自信のアイテムとして格納するときに、前後のダブルクォーテーションは削除されます。
	 * 
	 * @param line	CSVレコード解析を行う文字列行（つまり、CSVの１ライン）
	 */
	public void analizeRecord(String line) {
		this.analizeRecord(line, null);
	}

	/**
	 * lineで示された文字列を、CSVレコードとして構文解析を行い、自身に取り込む.
	 * 取り込まれたセル文字列は、自信(LinkedList)のアイテムとして格納されます.
	 * 格納順序は、左から順に格納される.
	 * v2.17-2010/01/24より、ダブルクォーテーションで囲まれたセルを処理できるように変更しました。
	 * 自信のアイテムとして格納するときに、前後のダブルクォーテーションは削除されます。
	 * 
	 * @param line	CSVレコード解析を行う文字列行（つまり、CSVの１ライン）
	 * @param split 区切り記号。nullの時は「カンマ(,)」が使われる。
	 */
	public void analizeRecord(String line, String split) {
		this.clear();
		if (split == null) {
			split = ",";
		}
		boolean append = false;
		boolean sss = false;		// ダブルクォーテーション内かどうか
		StringBuffer sbuf = null;
		for (StringTokenizer st = new StringTokenizer(line, split + "\"", true); st.hasMoreTokens(); ) {
			String token = st.nextToken();
			if (token.equals("\"")) {
				if (sss) {
					// ダブルクォーテーションEND
					this.add(sbuf.toString());
					append = true;
					sss = false;
				}
				else {
					// ダブルクォーテーションSTART
					sbuf = new StringBuffer("");
					sss = true;
				}
			}
			else if (token.equals(split)) {
				if (sss) {
					sbuf.append(token);
				}
				else {
					if (append == false) {
						this.add("");
					}
					append = false;
				}
			}
			else {
				if (sss) {
					sbuf.append(token);
				}
				else {
					this.add(token.trim());
					append = true;
				}
			}
		}
		if (append == false) {
			this.add("");
		}
	}
	
	/**
	 * レコードの内容をＣＳＶ形式の文字列にして返す.
	 * 各項目はダブルクォーテーション(")で囲まれます。
	 * 各項目間は、カンマ(,)で区切られます。
	 * 
	 * @return このオブジェクトをCSVの１ライン形式として返します。
	 */
	public String toString() {
		return this.toString(null);
	}

	/**
	 * レコードの内容をＣＳＶ形式の文字列にして返す.
	 * 各項目はダブルクォーテーション(")で囲まれます。
	 * 
	 * @param split 区切り記号。nullの時は「カンマ(,)」が使われる。
	 * @return このオブジェクトをCSVの１ライン形式として返します。
	 */
	public String toString(String split) {
		StringBuffer ret = new StringBuffer();
		boolean top = true;
		for (String col : this) {
			if (top) {
				top = false;
			}
			else {
				ret.append(",");
			}
			ret.append("\""+ col +"\"");
		}
		return ret.toString();
	}
}
