/**
 * LOGICAL-PARADOX.ORG
 * Copyright (C)2004 satoshi akabane(akabane@logical-paradox.org)
 *
 */
package org.logical_paradox.kinako.logic.parser;

import org.logical_paradox.common.fsm.FiniteStateMachine;
import org.logical_paradox.common.fsm.Symbol;
import org.logical_paradox.phalanx.binding.condition.AndType;
import org.logical_paradox.phalanx.binding.condition.Condition;
import org.logical_paradox.phalanx.binding.condition.ObjectFactory;

/**
 * 入力されたキーワードを解析して，検索条件を生成する有限状態遷移機械
 * @author satoshi akabane@logical-paradox.org
 * @version $Revision: 1.2 $
 */
public class SearchConditionFsm extends FiniteStateMachine {
	/** 検索条件 */
	private Condition condition;
	/** 検索条件に関連するオブジェクトを生成するファクトリ */
	private ObjectFactory factory;
	/** 現在の状態 */
	private SearchConditionState state;
	private AndType and;
	private StringBuffer sb = new StringBuffer();

	/** セパレータシンボル */
	private static final Symbol SEPARATOR = new CharacterSymbol(' ');
	private static final SearchConditionState STATE_INITIAL = new SearchConditionState(SearchConditionState.INITIAL);
	private static final SearchConditionState STATE_ACCEPTING = new SearchConditionState(SearchConditionState.ACCEPTING);
	private static final SearchConditionState STATE_FINAL = new SearchConditionState(SearchConditionState.FINAL);

	/**
	 * コンストラクタ
	 * @param name 名称
	 */
	public SearchConditionFsm(String name) throws Exception {
		super(name);
	}
	/**
	 * 初期化する
	 */
	public void init() throws Exception {
		super.init();
		factory = new ObjectFactory();
		condition = factory.createCondition();
		state = new SearchConditionState();
		and = factory.createAndType();
	}
	/**
	 * 終了処理
	 * @throws Exception 処理中に発生した例外
	 */
	public void finish() throws Exception {
		// ステータスが中途半端であれば，正常終了処理を実行する
		if(state.equals(STATE_ACCEPTING)) {
			and.getTerm().add(sb.toString());
		}
		// 検索条件を生成する
		condition.getAnd().add(and);

		// 終了状態へ遷移
		state.transition(STATE_FINAL.getCurrentState());
	}
	/**
	 * 入力記号を状態に対して与える
	 * 入力された記号によって，状態が遷移したとされるタイミングでイベントが発生する
	 * @param symbol 入力記号
	 */
	protected void input(Symbol symbol) {
		if(symbol.equals(SEPARATOR)) {
			if(state.equals(STATE_ACCEPTING)) {
				// 一つの索引語の処理が完了した場合は，検索条件にtermを追加する
				and.getTerm().add(sb.toString());
				sb = new StringBuffer();
			}
			// セパレータを受信した場合は初期状態へ遷移
			state.transition(SearchConditionState.INITIAL);
		} else {
			// セパレータ以外は受信中の状態
			if(state.equals(STATE_INITIAL)) {
				// 初期状態から受信中状態へ遷移した場合，<AND>を追加する
				state.transition(SearchConditionState.ACCEPTING);
			}
			sb.append(symbol.toString());
		}
	}
	/**
	 * 現在の状態が終了状態にあるかどうかを返す
	 * @return true:終了状態 / false:継続状態
	 */
	protected boolean isFiniteState() {
		return STATE_FINAL.equals(state);
	}
	/**
	 * 結果を返す
	 * @return 結果
	 */
	public Object getResult() {
		return condition;
	}
}
