/* $Id: ConditionEvaluator.java,v 1.2 2007/11/05 09:50:54 nito Exp $
 *
 * Copyright (c)ARGO 21, Corporation. 2005, 2006.  All rights reserved.
 * 
 * This file is part of Nautica Workflow Core.
 * 
 *  Nautica Workflow Core is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation; either version 2.1 of the License, or
 *  (at your option) any later version.
 * 
 *  Nautica Workflow Core is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 * 
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with Nautica Workflow Core; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *  
 */
package jp.co.argo21.nautica.workflow.engine;

import java.util.ArrayList;
import java.util.List;

import jp.co.argo21.nautica.workflow.dataaccess.VariableBean;
import jp.co.argo21.nautica.workflow.definition.ActivityDefinition;
import jp.co.argo21.nautica.workflow.definition.ProcessDefinition;
import jp.co.argo21.nautica.workflow.definition.TransitionDefinition;
import jp.co.argo21.nautica.workflow.expression.Expression;

/**
 * 条件評価。
 *
 * @author  nito(Argo 21, Corp.)
 * @version $Revision: 1.2 $
 * @since   Nautica Workflow 1.0
 */
class ConditionEvaluator
{
	/**
	 * 条件の判定を行う。
	 * 
	 * @param pd プロセス定義
	 * @param ad アクティビティ定義
	 * @param vars	評価対象のプロセス変数
	 * @param isExRaising	例外発生
	 * @return	条件評価の結果、選択された遷移
	 */
	static List<TransitionDefinition> evaluate(
			ProcessDefinition pd, ActivityDefinition ad,
			List<VariableBean> vars, boolean isExRaising)
	{
		List<TransitionDefinition> result = new ArrayList<TransitionDefinition>();
		List<TransitionDefinition> otherwises = new ArrayList<TransitionDefinition>();
		boolean isConcurrent = false;

		if (ad.getType().equals(ActivityDefinition.CONCUR_START)) {
			isConcurrent = true;
		}

		for (TransitionDefinition tr : pd.getTransitions()) {

			//該当アクティビティの遷移情報ではない場合、スキップ
			if (ad != tr.getSource()) continue;

			Expression exp = tr.getCondition();
			int type = tr.getType();
			
			if (type == TransitionDefinition.EXCEPTION) {
				if (isExRaising) {
					result.add(tr);
					if (isConcurrent == false) break;
				}
			} else if (type == TransitionDefinition.OTHERWISE) {
				otherwises.add(tr);
			} else {
				if (exp == null) {
					//条件式がない場合は無条件遷移とみなす。
					result.add(tr);
					if (isConcurrent == false) break;
				} else {
					if (exp.eval(vars)) {
						result.add(tr);
						if (isConcurrent == false) break;
					}
				}
			}
		}

		//代替遷移の判定
		if (result.size() == 0) {
			if (otherwises.size() > 0) {
				if (isConcurrent) {
					result = otherwises;
				} else {
					result.add(otherwises.get(0));
				}
			}
		}

		return result;
	}

}
