/*
 * Copyright (c) 2009 The openGion Project.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package org.opengion.fukurou.util;

import java.io.FileInputStream;
import java.io.UnsupportedEncodingException;
import java.io.IOException;
import java.util.StringTokenizer;

/**
 * FileString は、ファイルを読み取って、そのまま String 文字列として返すクラスです。
 * SQLを記述したファイルや、コマンドを記述したファイルを読み取って、コマンドラインからの
 * 入力として利用できます。
 *
 * ファイルは、一旦すべて読み取ってメモリ上で加工されます。
 * パラメータ等の設定ファイルをイメージしている為、巨大なファイルの読み込みは出来ません。
 *
 * @version  4.0
 * @author   Kazuhiko Hasegawa
 * @since    JDK5.0,
 */
public class FileString  {
	private String	filename	;
	private String	encode		;
	private String	value		;

	/**
	 * ファイル名を設定します。
	 * 指定のファイルを読み取って、内部文字列に格納します。
	 * なお、格納するタイミングは、#getValue() を最初に行ったときです。
	 * ファイル名を再設定すると、内部のvalue は、クリアされます。
	 *
	 * @param  filename ファイル名
	 */
	public void setFilename( final String filename ) {
		if( filename == null ) {
			final String errMsg = "ファイル名が指定されていません。" ;
			throw new RuntimeException( errMsg );
		}

		this.filename = filename;
		value		  = null;		// 初期化
	}

	/**
	 * ファイル名を取得します。
	 *
	 * @og.rev 5.2.3.0 (2010/12/01) 新規追加
	 *
	 * @return	ファイル名
	 */
	public String getFilename() {
		return filename;
	}

	/**
	 * ファイルのエンコードを設定します。
	 * 指定のファイルを読み取る場合のエンコードを指定します。
	 * 正確には、バイナリデータを読み取って、文字列に変換する場合に、
	 * String( byte[],String ) コンストラクタの引数に使用します。
	 * 指定されていない場合は、String( byte[] ) コンストラクタで変換します。
	 * エンコードを再設定すると、内部のvalue は、クリアされます。
	 *
	 * @param  encode エンコード名
	 */
	public void setEncode( final String encode ) {
		this.encode	= encode;
		value		= null;		// 初期化
	}

	/**
	 * ファイルのエンコードを取得します。
	 * 正確には、内部文字列に変換したときのエンコードです。
	 * null の場合は、無指定(つまりデフォルトエンコード)と
	 * なります。
	 *
	 * @og.rev 5.2.3.0 (2010/12/01) 新規追加
	 *
	 * @return	ファイルのエンコード
	 */
	public String getEncode() {
		return encode;
	}

	/**
	 * ファイルを読み取って、文字列を作成します。
	 *
	 * データの読取が完全に出来なかったときには、途中までのデータを返します。
	 * 指定のエンコードが存在しない場合や、ファイルが存在しない場合は、
	 * RuntimeException を throw します。
	 *
	 * @return  ファイルを読み取った文字列
	 * @throws RuntimeException 指定のエンコードが存在しなかったとき。
	 */
	public String getValue() {
		if( value != null ) { return value; }

		FileInputStream file = null;
		try {
			file = new FileInputStream( filename );
			final byte[] buf = new byte[file.available()];
			final int len = file.read(buf);
			if( len != buf.length ) {
				final String errMsg = "読み取りファイルのデータが切り捨てられました。" +
								"File=" + filename + " Length=" + len ;
				LogWriter.log( errMsg );
			}
			if( encode != null ) {
				value = new String( buf,encode );
			}
			else {
				value = new String( buf,StringUtil.DEFAULT_CHARSET );	// 5.5.2.6 (2012/05/25) findbugs対応
			}
		}
		catch( UnsupportedEncodingException ex ) {
			final String errMsg = "指定されたエンコーディングがサポートされていません。[" + encode + "]" ;
			throw new RuntimeException( errMsg,ex );
		}
		catch( IOException ex ) {
			final String errMsg = "ファイル名がオープン出来ませんでした。[" + filename + "]" ;
			throw new RuntimeException( errMsg,ex );
		}
		finally {
			Closer.ioClose( file );
		}

		return value ;
	}

	/**
	 * 指定の区切り文字で分割された文字列配列を取得します。
	 * 区切り文字が連続している場合は、一つの区切り文字と認識します。
	 * 処理は、java.util.StringTokenizer で、処理する方法と同一です。
	 * 例えば、";" を指定すれば、SQL を複数記述しておくことが可能になります。
	 *
	 * @param	delim	ファイルを分割する区切り文字
	 *
	 * @return  ファイルを読み取った文字列
	 */
	public String[] getValue( final String delim ) {

		final StringTokenizer token = new StringTokenizer( getValue(),delim );

		String[] rtn = new String[token.countTokens()];

		for( int i=0; token.hasMoreTokens(); i++ ) {
			rtn[i] = token.nextToken();
		}

		return rtn ;
	}
}
