/* $Id: WorkflowEngineHandlerImpl.java,v 1.4 2007/11/26 08:51:40 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.List;

import org.apache.log4j.Logger;

import jp.co.argo21.nautica.workflow.dataaccess.ProcessBean;
import jp.co.argo21.nautica.workflow.dataaccess.ProcessDAO;
import jp.co.argo21.nautica.workflow.dataaccess.WorkflowDAOFactory;
import jp.co.argo21.nautica.workflow.definition.ActivityDefinition;
import jp.co.argo21.nautica.workflow.definition.ProcessDefinition;
import jp.co.argo21.nautica.workflow.filter.StateFilter;
import jp.co.argo21.nautica.workflow.jms.WorkflowMessage;
import jp.co.argo21.nautica.workflow.omg.AlreadyRunningException;
import jp.co.argo21.nautica.workflow.omg.NotRunningException;
import jp.co.argo21.nautica.workflow.omg.WfActivity;
import jp.co.argo21.nautica.workflow.omg.WfProcess;
import jp.co.argo21.nautica.workflow.omg.WfProcessManager;
import jp.co.argo21.nautica.workflow.omg.WfRequester;
import jp.co.argo21.nautica.workflow.omg.WfState;
import jp.co.argo21.nautica.workflow.omg.WorkflowException;
import jp.co.argo21.nautica.workflow.security.SessionManager;
import jp.co.argo21.nautica.workflow.util.StateHelper;
import jp.co.argo21.nautica.workflow.util.StringManager;
import jp.co.argo21.nautica.workflow.wfmc.Activity;
import jp.co.argo21.nautica.workflow.wfmc.ActivityState;
import jp.co.argo21.nautica.workflow.wfmc.Attribute;
import jp.co.argo21.nautica.workflow.wfmc.AttributeAssignmentFailedException;
import jp.co.argo21.nautica.workflow.wfmc.Filter;
import jp.co.argo21.nautica.workflow.wfmc.InvalidActivityInstanceException;
import jp.co.argo21.nautica.workflow.wfmc.InvalidAttributeException;
import jp.co.argo21.nautica.workflow.wfmc.InvalidFilterException;
import jp.co.argo21.nautica.workflow.wfmc.InvalidProcessDefinitionException;
import jp.co.argo21.nautica.workflow.wfmc.InvalidProcessInstanceException;
import jp.co.argo21.nautica.workflow.wfmc.InvalidSessionException;
import jp.co.argo21.nautica.workflow.wfmc.InvalidStateException;
import jp.co.argo21.nautica.workflow.wfmc.Process;
import jp.co.argo21.nautica.workflow.wfmc.ProcessState;
import jp.co.argo21.nautica.workflow.wfmc.TransitionNotAllowedException;
import jp.co.argo21.nautica.workflow.wfmc.WorkflowEngineHandler;

/**
 * WorkflowEngineHandlerImplは、ワークフローエンジンに対する
 * クライアントインタフェースの具体実装クラスである。
 *
 * @author  nito(Argo 21, Corp.)
 * @version $Revision: 1.4 $
 * @since   Nautica Workflow 1.0
 */
public class WorkflowEngineHandlerImpl implements WorkflowEngineHandler
{
	/** エンジンログ */
	private static Logger eLog = LogManager.getEngineLogger();
	
	/** 監査ログ */
	private static Logger audit = LogManager.getAuditLogger();

	/**
	 * WorkflowEngineHandlerImplを生成する。
	 */
	WorkflowEngineHandlerImpl()
	{
	}

	/**
	 * プロセスインスタンスの生成を行う。
	 *
	 * @param session セッションID
	 * @param pdid プロセス定義ID
	 * @param name プロセスインスタンス名称
	 * @return プロセスインスタンスID
	 * @throws InvalidSessionException 指定されたセッションが無効の場合
	 * @throws InvalidProcessDefinitionException 指定されたプロセス定義IDが有効でない場合
	 * @see jp.co.argo21.nautica.workflow.wfmc.WorkflowEngineHandler#createProcess(java.lang.String, java.lang.String, java.lang.String)
	 */
	public String createProcess(String session, String pdid, String name)
	throws InvalidSessionException, InvalidProcessDefinitionException
	{
		String argInfo = "(NAUTICA API = createProcess,"
			 + "session = [" + session + "],"
			 + "pdid = [" + pdid + "],"
			 + "name = [" + name + "])";
	
		try {
			if (pdid == null || pdid.trim().equals("")) {
				// プロセス定義IDが未設定です。
				String E0188 = StringManager.get("E0188");
				throw new InvalidProcessDefinitionException(E0188);
			}
		
			DataAccessManager.begin(false);
				
			validateSession(session);
	
			RequesterManager rqm = RequesterManager.getInstance();
			WfRequester requester = rqm.getRequesterBySession(session);
			ProcessManagerFactory pmf = ProcessManagerFactory.getInstance();
			WfProcessManager pm = pmf.getProcessManager(pdid);
			String pid = null;
			WfProcess process = pm.createProcess(requester, name);
			pid = process.getID(); 
			
			DataAccessManager.commit();
				
			// 監査ログ出力
		    AuditDataRecord data = new AuditDataRecord(
		            new AuditPrefix("", "WMCreatedProcessInstance", session),
		            new AuditSuffix());
		    data.setDataElement("ProcessDefinitionID", pdid);
		    data.setDataElement("ProcessDefinitionBusinessName", name);		    
		    audit.info(data);
	
			return pid;
		} catch (InvalidSessionException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidProcessDefinitionException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (Exception ex) {
			try { DataAccessManager.rollback(); } catch (Exception ex2) { /* Ignore */ }
			// プロセスの生成に失敗しました。
			String E0153 = StringManager.get("E0153") + argInfo;
			eLog.error(E0153, ex);
			throw new InvalidProcessDefinitionException(E0153, ex);
		} finally {
			try { DataAccessManager.close(); } catch (Exception ex) { /* Ignore */ }
		}
	}

	/**
	 * プロセスインスタンスの開始を行う。
	 * 開始した場合に、プロセスインスタンスIDを更新するような
	 * 実装も可能である。
	 *
	 * @param session セッションID
	 * @param pid プロセスインスタンスID
	 * @return 更新されたプロセスインスタンスID
	 * @throws InvalidSessionException 指定されたセッションが無効の場合
	 * @throws InvalidProcessInstanceException プロセスインスタンスIDが有効でない場合
	 * @throws InvalidAttributeException 属性が有効でない場合
	 * @see jp.co.argo21.nautica.workflow.wfmc.WorkflowEngineHandler#startProcess(java.lang.String, java.lang.String)
	 */
	public String startProcess(String session, String pid)
	throws InvalidSessionException, InvalidProcessInstanceException,
		InvalidAttributeException
	{
		String argInfo = "(NAUTICA API = startProcess,"
			 + "session = [" + session + "],"
			 + "pid = [" + pid + "])";
	
		try {
			checkProcessID(pid);
			
			DataAccessManager.begin(false);
				
			validateSession(session);

			//プロセスの存在チェック
			WorkflowDAOFactory daoFactory = DataAccessManager.getDAOFactory();
			ProcessDAO procDAO = daoFactory.getProcessDAO();
			ProcessBean bean = procDAO.findByPrimaryKey(pid);
			if (bean == null) {
				// プロセスが存在しません。
				String E0164 = StringManager.get("E0164");
				throw new InvalidProcessInstanceException(E0164);
			}
			ProcessState state = ProcessState.getState(bean.getProcessState());
			if (ProcessState.CLOSED_COMPLETED.equals(state)
					|| ProcessState.CLOSED_TERMINATED.equals(state)
					|| ProcessState.CLOSED_ABORTED.equals(state)) {
				// プロセスはすでに終了しています。
				String E0128 = StringManager.get("E0128");
				throw new NotRunningException(E0128);
			} else if (ProcessState.OPEN_NOT_RUNNING_NOT_STARTED.equals(state) == false) {
				// プロセスはすでに開始しています。
				String E0129 = StringManager.get("E0129");
				throw new AlreadyRunningException(E0129);
			}
	
			//メッセージキューに登録
			WorkflowMessage msg = new StartProcessRequestMessage(pid);
			WorkflowEngine engine = WorkflowEngine.getInstance();
			MessageTransporter mt = engine.getMessageTransporter(session, StartProcessRequestWatcher.NAME);
			mt.sendMessage(msg);
				
			DataAccessManager.commit();
				
			// 監査ログ出力
		    AuditDataRecord data = new AuditDataRecord(
		            new AuditPrefix(pid, "WMStartedProcessInstance", session),
		            new AuditSuffix());
		    audit.info(data);
	
			return pid;
		} catch (InvalidSessionException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidProcessInstanceException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (Exception ex) {
			try { DataAccessManager.rollback(); } catch (Exception ex2) { /* Ignore */ }
			// プロセスの開始に失敗しました。
			String E0132 = StringManager.get("E0132") + argInfo;
			eLog.error(E0132, ex);
			throw new InvalidProcessInstanceException(E0132, ex);
		} finally {
			try { DataAccessManager.close(); } catch (Exception ex) { /* Ignore */ }
		}
	}

	/**
	 * プロセスインスタンスの停止を行う。
	 *
	 * @param session セッションID
	 * @param pid プロセスインスタンスID
	 * @throws InvalidSessionException 指定されたセッションが無効の場合
	 * @throws InvalidProcessInstanceException プロセスインスタンスIDが有効でない場合
	 * @see jp.co.argo21.nautica.workflow.wfmc.WorkflowEngineHandler#terminateProcess(java.lang.String, java.lang.String)
	 */
	public void terminateProcess(String session, String pid)
	throws InvalidSessionException, InvalidProcessInstanceException
	{
		String argInfo = "(NAUTICA API = terminateProcess,"
			 + "session = [" + session + "],"
			 + "pid = [" + pid + "])";
	
		try {
			checkProcessID(pid);
			
			DataAccessManager.begin(false);
				
			validateSession(session);
				
			ProcessManagerFactory pmf = ProcessManagerFactory.getInstance();
			ProcessManager pm = pmf.getOwnerProcessManager(pid);
			ProcessInternal proc = (ProcessInternal)pm.getProcess(pid);
	
			proc.terminate();
							
			DataAccessManager.commit();
				
			// 監査ログ出力
		    AuditDataRecord data = new AuditDataRecord(
		            new AuditPrefix(pid, "WMTerminatedProcessInstance", session),
		            new AuditSuffix());
		    data.setDataElement("NewProcessState", ProcessState.CLOSED_TERMINATED);
		    audit.info(data);

		} catch (InvalidSessionException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidProcessInstanceException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (Exception ex) {
			try { DataAccessManager.rollback(); } catch (Exception ex2) { /* Ignore */ }
			// プロセスの停止に失敗しました。
			String E0136 = StringManager.get("E0136") + argInfo;
			eLog.error(E0136, ex);
			throw new InvalidProcessInstanceException(E0136, ex);
		} finally {
			try { DataAccessManager.close(); } catch (Exception ex) { /* Ignore */ }
		}
	}

	/**
	 * 指定されたプロセスインスタンスが利用可能な状態一覧の取得を行う。
	 * 利用可能なフィルターはStateFilterのみとする。
	 *
	 * @param session セッションID
	 * @param pid プロセスインスタンスID
	 * @param filter 検索用フィルター
	 * @return プロセスインスタンス状態一覧
	 * @throws InvalidSessionException 指定されたセッションが無効の場合
	 * @throws InvalidProcessInstanceException プロセスインスタンスIDが有効でない場合
	 * @throws InvalidFilterException 指定されたフィルターが有効でない場合
	 * @see jp.co.argo21.nautica.workflow.wfmc.WorkflowEngineHandler#getProcessStates(java.lang.String, java.lang.String, jp.co.argo21.nautica.workflow.wfmc.Filter)
	 */
	public ProcessState[] getProcessStates(String session, 
			String pid, Filter filter)
	throws InvalidSessionException, InvalidProcessInstanceException,
		InvalidFilterException
	{
		String argInfo = "(NAUTICA API = getProcessStates,"
			 + "session = [" + session + "],"
			 + "pid = [" + pid + "],"
			 + "filter = [" + filter + "])";

		ProcessState state = null;
		try {
			checkProcessID(pid);
			
			DataAccessManager.begin(false);
				
			validateSession(session);
	
			//StateFilterのみを対象とする。
			if (filter != null) {
				if (filter instanceof StateFilter) {
					WfState st = ((StateFilter)filter).getState();
					if (st instanceof ProcessState) {
						state = (ProcessState)st;
					} else {
						//設定されている状態は、プロセス状態ではありません。
						String E0205 = StringManager.get("E0205");
						throw new InvalidFilterException(E0205);
					}
				} else {
					// 状態フィルター以外は使用できません。
					String E0184 = StringManager.get("E0184");
					throw new InvalidFilterException(E0184);
				}
			}
	
			ProcessManagerFactory pmf = ProcessManagerFactory.getInstance();
			WfProcessManager pm = pmf.getOwnerProcessManager(pid);
			WfProcess process = pm.getProcess(pid);
			ProcessState cstate = (ProcessState)process.getState();
			ProcessState[] tstates = null;
			if (state == null) {
				tstates = (ProcessState[])process.getTransitableStates();
			} else {
				if (StateHelper.containsTransitable(cstate, state)) {
					tstates = new ProcessState[1];
					tstates[0] = state;
				} else {
					tstates = new ProcessState[0];
				}
			}
			
			DataAccessManager.commit();
	
			return tstates;
		} catch (InvalidSessionException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidProcessInstanceException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidFilterException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (Exception ex) {
			try { DataAccessManager.rollback(); } catch (Exception ex2) { /* Ignore */ }
			// プロセス状態の取得に失敗しました。
			String E0154 = StringManager.get("E0154") + argInfo;
			eLog.error(E0154, ex);
			throw new InvalidProcessInstanceException(E0154, ex);
		} finally {
			try { DataAccessManager.close(); } catch (Exception ex) { /* Ignore */ }
		}
	} 

	/**
	 * プロセスインスタンス状態の変更を行う。
	 *
	 * @param session セッションID
	 * @param pid プロセスインスタンスID
	 * @param state プロセスインスタンス状態
	 * @throws InvalidSessionException 指定されたセッションが無効の場合
	 * @throws InvalidProcessInstanceException プロセスインスタンスIDが有効でない場合
	 * @throws InvalidStateException 指定された状態が有効でない場合
	 * @throws TransitionNotAllowedException 状態の変更が許可されていない場合
	 * @see jp.co.argo21.nautica.workflow.wfmc.WorkflowEngineHandler#changeProcessState(java.lang.String, java.lang.String, jp.co.argo21.nautica.workflow.wfmc.ProcessState)
	 */
	public void changeProcessState(String session,
			String pid, ProcessState state)
	throws InvalidSessionException, InvalidProcessInstanceException,
		InvalidStateException, TransitionNotAllowedException
	{
		String argInfo = "(NAUTICA API = changeProcessState,"
			 + "session = [" + session + "],"
			 + "pid = [" + pid + "],"
			 + "state = [" + state + "])";

		try {
			DataAccessManager.begin(false);
				
			validateSession(session);

			checkProcessID(pid);
				
			if (state == null) {
				// プロセスの状態が設定されていません。
				String E0063 = StringManager.get("E0063");
				throw new InvalidStateException(E0063);
			} else if (ProcessState.OPEN_NOT_RUNNING_NOT_STARTED.equals(state)) {
				// プロセスの状態を未開始にすることはできません。
				String E0064 = StringManager.get("E0064");
				throw new InvalidStateException(E0064);
			} else if (ProcessState.CLOSED_COMPLETED.equals(state)) {
				// プロセスの状態を強制的に正常終了させることはできません。
				String E0065 = StringManager.get("E0065");
				throw new InvalidStateException(E0065);
			}

			ProcessManagerFactory pmf = ProcessManagerFactory.getInstance();
			WfProcessManager pm = pmf.getOwnerProcessManager(pid);
			WfProcess process = pm.getProcess(pid);
			process.changeState(state);
			
			DataAccessManager.commit();
				
			// 監査ログ出力
		    AuditDataRecord data = new AuditDataRecord(
		            new AuditPrefix(pid, "WMChangedProcessInstanceState", session),
		            new AuditSuffix());
		    data.setDataElement("NewProcessState", state);		    
		    audit.info(data);
	
		} catch (InvalidSessionException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidProcessInstanceException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidStateException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (TransitionNotAllowedException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (Exception ex) {
			try { DataAccessManager.rollback(); } catch (Exception ex2) { /* Ignore */ }
			// プロセス状態の変更に失敗しました。
			String E0156 = StringManager.get("E0156") + argInfo;
			eLog.error(E0156, ex);
			throw new InvalidProcessInstanceException(E0156, ex);
		} finally {
			try { DataAccessManager.close(); } catch (Exception ex) { /* Ignore */ }
		}
	}

	/**
	 * プロセスインスタンス属性一覧の取得を行う。
	 * 利用可能なフィルターはNameFilter, AttributeFilter, GroupFilterとする。
	 *
	 * @param session セッションID
	 * @param pid プロセスインスタンスID
	 * @param filter 検索用フィルター
	 * @return 属性一覧
	 * @throws InvalidSessionException 指定されたセッションが無効の場合
	 * @throws InvalidProcessInstanceException プロセスインスタンスIDが有効でない場合
	 * @throws InvalidFilterException 指定されたフィルターが有効でない場合
	 * @see jp.co.argo21.nautica.workflow.wfmc.WorkflowEngineHandler#getProcessAttributes(java.lang.String, java.lang.String, jp.co.argo21.nautica.workflow.wfmc.Filter)
	 */
	public Attribute[] getProcessAttributes(String session,
			String pid, Filter filter)
	throws InvalidSessionException, InvalidProcessInstanceException,
		InvalidFilterException
	{
		String argInfo = "(NAUTICA API = getProcessAttributes,"
			 + "session = [" + session + "],"
			 + "pid = [" + pid + "],"
			 + "filter = [" + filter + "])";

		try {
			checkProcessID(pid);
			
			DataAccessManager.begin(false);
			
			validateSession(session);
	
			ProcessManagerFactory pmf = ProcessManagerFactory.getInstance();
			WfProcessManager pm = pmf.getOwnerProcessManager(pid);
			ProcessInternal process = (ProcessInternal)pm.getProcess(pid);
			Attribute[] attrs = (Attribute[])process.getContext(filter);
				
			DataAccessManager.commit();
	
			return attrs;
		} catch (InvalidSessionException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidProcessInstanceException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidFilterException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (Exception ex) {
			try { DataAccessManager.rollback(); } catch (Exception ex2) { /* Ignore */ }
			// プロセス変数の取得に失敗しました。
			String E0032 = StringManager.get("E0032") + argInfo;
			eLog.error(E0032, ex);
			throw new InvalidProcessInstanceException(E0032, ex);
		} finally {
			try { DataAccessManager.close(); } catch (Exception ex) { /* Ignore */ }
		}
	}

	/**
	 * プロセスインスタンス属性の属性値の取得を行う。
	 *
	 * @param session セッションID
	 * @param pid プロセスインスタンスID
	 * @param name 属性名
	 * @return 属性
	 * @throws InvalidSessionException 指定されたセッションが無効の場合
	 * @throws InvalidAttributeException 属性が有効でない場合
	 * @see jp.co.argo21.nautica.workflow.wfmc.WorkflowEngineHandler#getProcessAttributeValue(java.lang.String, java.lang.String, java.lang.String)
	 */
	public Attribute getProcessAttributeValue(String session,
			String pid, String name)
	throws InvalidSessionException, InvalidAttributeException
	{
		String argInfo = "(NAUTICA API = getProcessAttributeValue,"
			 + "session = [" + session + "],"
			 + "pid = [" + pid + "],"
			 + "name = [" + name + "])";

		try {
			
			if (pid == null || pid.trim().equals("")) {
				// プロセスIDが未設定です。
				String E0189 = StringManager.get("E0189");
				throw new InvalidAttributeException(E0189);
			}
		
			if (name == null || name.trim().equals("")) {
				// プロセス変数名が未設定です。
				String E0198 = StringManager.get("E0198");
				throw new InvalidAttributeException(E0198);
			}

			DataAccessManager.begin(false);
		
			validateSession(session);
	
			ProcessManagerFactory pmf = ProcessManagerFactory.getInstance();
			WfProcessManager pm = pmf.getOwnerProcessManager(pid);
			WfProcess process = pm.getProcess(pid);
			Attribute attr = (Attribute)process.getContext(name);
				
			DataAccessManager.commit();
	
			return attr;
		} catch (InvalidSessionException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidAttributeException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (Exception ex) {
			try { DataAccessManager.rollback(); } catch (Exception ex2) { /* Ignore */ }
			// プロセス変数の取得に失敗しました。
			String E0032 = StringManager.get("E0032") + argInfo;
			eLog.error(E0032, ex);
			throw new InvalidAttributeException(E0032, ex);
		} finally {
			try { DataAccessManager.close(); } catch (Exception ex) { /* Ignore */ }
		}
	}

	/**
	 * プロセスインスタンス属性の割り当てを行う。
	 *
	 * @param session セッションID
	 * @param pid プロセスインスタンスID
	 * @param attr 属性
	 * @throws InvalidSessionException 指定されたセッションが無効の場合
	 * @throws InvalidProcessInstanceException プロセスインスタンスIDが有効でない場合
	 * @throws InvalidAttributeException 属性が有効でない場合
	 * @throws AttributeAssignmentFailedException 属性の割り当てに失敗した場合
	 * @see jp.co.argo21.nautica.workflow.wfmc.WorkflowEngineHandler#assignProcessAttribute(java.lang.String, java.lang.String, jp.co.argo21.nautica.workflow.wfmc.Attribute)
	 */
	public void assignProcessAttribute(String session,
			String pid, Attribute attr)
	throws InvalidSessionException, InvalidProcessInstanceException,
		InvalidAttributeException, AttributeAssignmentFailedException
	{
		String argInfo = "(NAUTICA API = assignProcessAttribute,"
			 + "session = [" + session + "],"
			 + "pid = [" + pid + "],"
			 + "attr = [" + attr + "])";

		try {
			checkProcessID(pid);
			
			if (attr == null) {
				// プロセス変数が未設定です。
				String E0131 = StringManager.get("E0131");
				throw new InvalidAttributeException(E0131);
			}
			
			DataAccessManager.begin(false);
				
			validateSession(session);
	
			ProcessManagerFactory pmf = ProcessManagerFactory.getInstance();
			WfProcessManager pm = pmf.getOwnerProcessManager(pid);
			WfProcess process = pm.getProcess(pid);
			process.setContext(attr);
				
			DataAccessManager.commit();
				
			// 監査ログ出力
		    AuditDataRecord data = new AuditDataRecord(
		            new AuditPrefix(pid, "WMAssignedProcessInstanceAttributes", session),
		            new AuditSuffix());
		    data.setDataElement("AttributeName", attr.getName());
		    data.setDataElement("AttributeType", attr.getType());
		    data.setDataElement("NewAttributeValue", attr.getValue());
		    audit.info(data);
	
		} catch (InvalidSessionException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidProcessInstanceException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidAttributeException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (AttributeAssignmentFailedException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (Exception ex) {
			try { DataAccessManager.rollback(); } catch (Exception ex2) { /* Ignore */ }
			// プロセス変数の設定に失敗しました。
			String E0080 = StringManager.get("E0080") + argInfo;
			eLog.error(E0080, ex);
			throw new InvalidAttributeException(E0080, ex);
		} finally {
			try { DataAccessManager.close(); } catch (Exception ex) { /* Ignore */ }
		}
	}

	/**
	 * 指定されたアクティビティインスタンスが利用可能な状態一覧の取得を行う。
	 * 利用可能なフィルターはStateFilterのみとする。
	 *
	 * @param session セッションID
	 * @param pid プロセスインスタンスID
	 * @param aid アクティビティインスタンスID
	 * @param filter 検索用フィルター
	 * @return アクティビティインスタンス状態一覧
	 * @throws InvalidSessionException 指定されたセッションが無効の場合
	 * @throws InvalidProcessInstanceException プロセスインスタンスIDが有効でない場合
	 * @throws InvalidActivityInstanceException アクティビティインスタンスIDが有効でない場合
	 * @throws InvalidFilterException 指定されたフィルターが有効でない場合
	 * @see jp.co.argo21.nautica.workflow.wfmc.WorkflowEngineHandler#getActivityStates(java.lang.String, java.lang.String, java.lang.String, jp.co.argo21.nautica.workflow.wfmc.Filter)
	 */
	public ActivityState[] getActivityStates(String session,
			String pid, String aid, Filter filter)
	throws InvalidSessionException, InvalidProcessInstanceException,
		InvalidActivityInstanceException, InvalidFilterException
	{
		String argInfo = "(NAUTICA API = getActivityStates,"
			 + "session = [" + session + "],"
			 + "pid = [" + pid + "],"
			 + "aid = [" + aid + "],"
			 + "filter = [" + filter + "])";

		ActivityState state = null;
		try {
			checkProcessID(pid);
			checkActivityID(aid);
		
			DataAccessManager.begin(false);
				
			validateSession(session);
	
			//StateFilterのみを対象とする。
			if (filter != null) {
				if (filter instanceof StateFilter) {
					WfState st = ((StateFilter)filter).getState();
					if (st instanceof ActivityState) {
						state = (ActivityState)st;
					} else {
						// 設定されている状態は、アクティビティ状態ではありません。
						String E0206 = StringManager.get("E0206");
						throw new InvalidFilterException(E0206);
					}
				} else {
					// 状態フィルター以外は使用できません。
					String E0184 = StringManager.get("E0184");
					throw new InvalidFilterException(E0184);
				}
			}
	
			ProcessManagerFactory pmf = ProcessManagerFactory.getInstance();
			WfProcessManager pm = pmf.getOwnerProcessManager(pid);
			WfProcess process = pm.getProcess(pid);
			WfActivity activity = process.getStep(aid);
			if (activity == null) {
				// 該当するアクティビティが存在しません。
				String msg = StringManager.get("E0069");
				throw new InvalidActivityInstanceException(msg);
			}
			ActivityState cstate = (ActivityState)activity.getState();
			ActivityState[] tstates = null;
			if (state == null) {
				tstates = (ActivityState[])activity.getTransitableStates();
			} else {
				if (StateHelper.containsTransitable(cstate, state)) {
					tstates = new ActivityState[1];
					tstates[0] = state;
				} else {
					tstates = new ActivityState[0];
				}
			}
				
			DataAccessManager.commit();
	
			return tstates;
		} catch (InvalidSessionException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidProcessInstanceException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidActivityInstanceException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidFilterException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (Exception ex) {
			try { DataAccessManager.rollback(); } catch (Exception ex2) { /* Ignore */ }
			// アクティビティ状態の取得に失敗しました。
			String E0200 = StringManager.get("E0200") + argInfo;
			eLog.error(E0200, ex);
			throw new InvalidActivityInstanceException(E0200, ex);
		} finally {
			try { DataAccessManager.close(); } catch (Exception ex) { /* Ignore */ }
		}
	}

	/**
	 * アクティビティインスタンス状態の変更を行う。
	 *
	 * @param session セッションID
	 * @param pid プロセスインスタンスID
	 * @param aid アクティビティインスタンスID
	 * @param state アクティビティインスタンス状態
	 * @throws InvalidSessionException 指定されたセッションが無効の場合
	 * @throws InvalidProcessInstanceException プロセスインスタンスIDが有効でない場合
	 * @throws InvalidActivityInstanceException アクティビティインスタンスIDが有効でない場合
	 * @throws InvalidStateException 指定された状態が有効でない場合
	 * @throws TransitionNotAllowedException 状態の変更が許可されていない場合
	 * @see jp.co.argo21.nautica.workflow.wfmc.WorkflowEngineHandler#changeActivityState(java.lang.String, java.lang.String, java.lang.String, jp.co.argo21.nautica.workflow.wfmc.ActivityState)
	 */
	public void changeActivityState(String session,
			String pid, String aid, ActivityState state)
	throws InvalidSessionException, InvalidProcessInstanceException,
		InvalidActivityInstanceException, InvalidStateException,
		TransitionNotAllowedException
	{
		String argInfo = "(NAUTICA API = changeActivityState,"
			 + "session = [" + session + "],"
			 + "pid = [" + pid + "],"
			 + "aid = [" + aid + "],"
			 + "state = [" + state + "])";

		try {
			checkProcessID(pid);
			checkActivityID(aid);
		
			if (state == null) {
				// アクティビティの状態が設定されていません。
				String msg = StringManager.get("E0066");
				throw new InvalidStateException(msg);
			} else if (ActivityState.OPEN_NOT_RUNNING_NOT_STARTED.equals(state)) {
				// アクティビティの状態を未開始にすることはできません。
				String msg = StringManager.get("E0067");
				throw new InvalidStateException(msg);
			//} else if (ActivityState.CLOSED_COMPLETED.equals(state)) {
				// アクティビティの状態を強制的に正常終了させることはできません。
				//String msg = StringManager.get("E0068");
				//throw new InvalidStateException(msg);
			}
		
			DataAccessManager.begin(false);
				
			validateSession(session);
	
			ProcessManagerFactory pmf = ProcessManagerFactory.getInstance();
			WfProcessManager pm = pmf.getOwnerProcessManager(pid);
			WfProcess process = pm.getProcess(pid);
			WfActivity activity = process.getStep(aid);
			if (activity == null) {
				// 該当するアクティビティが存在しません。
				String msg = StringManager.get("E0069");
				throw new InvalidActivityInstanceException(msg);
			}
			activity.changeState(state);
				
			DataAccessManager.commit();
			
			// 監査ログ出力
		    AuditDataRecord data = new AuditDataRecord(
		            new AuditPrefix(pid, "WMChangedActivityInstanceState", session),
		            new AuditSuffix());
		    data.setDataElement("ActivityInstanceID", aid);
		    data.setDataElement("ActivityDefinitionBusinessName", activity.getName());
		    data.setDataElement("NewActivityState", state);
		    audit.info(data);
	
		} catch (InvalidSessionException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidProcessInstanceException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidActivityInstanceException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidStateException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (TransitionNotAllowedException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (Exception ex) {
			try { DataAccessManager.rollback(); } catch (Exception ex2) { /* Ignore */ }
			// アクティビティ状態の変更に失敗しました。
			String E0157 = StringManager.get("E0157") + argInfo;
			eLog.error(E0157, ex);
			throw new TransitionNotAllowedException(E0157, ex);
		} finally {
			try { DataAccessManager.close(); } catch (Exception ex) { /* Ignore */ }
		}
	}

	/**
	 * アクティビティインスタンス属性一覧の取得を行う。
	 * 利用可能なフィルターはNameFilter, AttributeFilter, GroupFilterとする。
	 *
	 * @param session セッションID
	 * @param pid プロセスインスタンスID
	 * @param aid アクティビティインスタンスID
	 * @param filter 検索用フィルター
	 * @return アクティビティインスタンス属性一覧
	 * @throws InvalidSessionException 指定されたセッションが無効の場合
	 * @throws InvalidProcessInstanceException プロセスインスタンスIDが有効でない場合
	 * @throws InvalidActivityInstanceException アクティビティインスタンスIDが有効でない場合
	 * @throws InvalidFilterException 指定されたフィルターが有効でない場合
	 * @see jp.co.argo21.nautica.workflow.wfmc.WorkflowEngineHandler#getActivityAttributes(java.lang.String, java.lang.String, java.lang.String, jp.co.argo21.nautica.workflow.wfmc.Filter)
	 */
	public Attribute[] getActivityAttributes(String session,
			String pid, String aid, Filter filter)
	throws InvalidSessionException, InvalidProcessInstanceException,
		InvalidActivityInstanceException, InvalidFilterException
	{
		String argInfo = "(NAUTICA API = getActivityAttributes,"
			 + "session = [" + session + "],"
			 + "pid = [" + pid + "],"
			 + "aid = [" + aid + "],"
			 + "filter = [" + filter + "])";

		try {
			checkProcessID(pid);
			checkActivityID(aid);
		
			DataAccessManager.begin(false);
				
			validateSession(session);
	
			ProcessManagerFactory pmf = ProcessManagerFactory.getInstance();
			WfProcessManager pm = pmf.getOwnerProcessManager(pid);
			WfProcess process = pm.getProcess(pid);
			ActivityInternal activity = (ActivityInternal)process.getStep(aid);
			if (activity == null) {
				// 該当するアクティビティが存在しません。
				String msg = StringManager.get("E0069");
				throw new InvalidActivityInstanceException(msg);
			}
			Attribute[] attrs = (Attribute[])activity.getContext(filter);
				
			DataAccessManager.commit();
	
			return attrs;
		} catch (InvalidSessionException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidProcessInstanceException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidActivityInstanceException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidFilterException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (Exception ex) {
			try { DataAccessManager.rollback(); } catch (Exception ex2) { /* Ignore */ }
			// アクティビティ指定のプロセス変数の取得に失敗しました。
			String E0201 = StringManager.get("E0201") + argInfo;
			eLog.error(E0201, ex);
			throw new InvalidProcessInstanceException(E0201, ex);
		} finally {
			try { DataAccessManager.close(); } catch (Exception ex) { /* Ignore */ }
		}
	}

	/**
	 * アクティビティインスタンス属性の属性値の取得を行う。
	 *
	 * @param session セッションID
	 * @param pid プロセスインスタンスID
	 * @param aid アクティビティインスタンスID
	 * @param name 属性名
	 * @return 属性
	 * @throws InvalidSessionException 指定されたセッションが無効の場合
	 * @throws InvalidAttributeException 属性が有効でない場合
	 * @see jp.co.argo21.nautica.workflow.wfmc.WorkflowEngineHandler#getActivityAttributeValue(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
	 */
	public Attribute getActivityAttributeValue(String session,
			String pid, String aid, String name)
	throws InvalidSessionException, InvalidAttributeException
	{
		String argInfo = "(NAUTICA API = getActivityAttributeValue,"
			 + "session = [" + session + "],"
			 + "pid = [" + pid + "],"
			 + "aid = [" + aid + "],"
			 + "name = [" + name + "])";

		try {
			if (pid == null || pid.trim().equals("")) {
				// プロセスIDが未設定です。
				String E0189 = StringManager.get("E0189");
				throw new InvalidAttributeException(E0189);
			}

			if (aid == null || aid.trim().equals("")) {
				// アクティビティIDが未設定です。
				String E0197 = StringManager.get("E0197");
				throw new InvalidAttributeException(E0197);
			}

			if (name == null || name.trim().equals("")) {
				// プロセス変数名が未設定です。
				String E0198 = StringManager.get("E0198");
				throw new InvalidAttributeException(E0198);
			}

			DataAccessManager.begin(false);
				
			validateSession(session);
	
			ProcessManagerFactory pmf = ProcessManagerFactory.getInstance();
			WfProcessManager pm = pmf.getOwnerProcessManager(pid);
			WfProcess process = pm.getProcess(pid);
			WfActivity activity = process.getStep(aid);
			if (activity == null) {
				// 該当するアクティビティが存在しません。
				String msg = StringManager.get("E0069");
				throw new InvalidActivityInstanceException(msg);
			}
			Attribute attr = (Attribute)activity.getContext(name);
				
			DataAccessManager.commit();
	
			return attr;
		} catch (InvalidSessionException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidAttributeException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (Exception ex) {
			try { DataAccessManager.rollback(); } catch (Exception ex2) { /* Ignore */ }
			// アクティビティ指定のプロセス変数の取得に失敗しました。
			String E0201 = StringManager.get("E0201") + argInfo;
			eLog.error(E0201, ex);
			throw new InvalidAttributeException(E0201, ex);
		} finally {
			try { DataAccessManager.close(); } catch (Exception ex) { /* Ignore */ }
		}
	}

	/**
	 * アクティビティインスタンス属性の割り当てを行う。
	 *
	 * @param session セッションID
	 * @param pid プロセスインスタンスID
	 * @param aid アクティビティインスタンスID
	 * @param attr 属性
	 * @throws InvalidSessionException 指定されたセッションが無効の場合
	 * @throws InvalidProcessInstanceException プロセスインスタンスIDが有効でない場合
	 * @throws InvalidActivityInstanceException アクティビティインスタンスIDが有効でない場合
	 * @throws InvalidAttributeException 属性が有効でない場合
	 * @throws AttributeAssignmentFailedException 属性の割り当てに失敗した場合
	 * @see jp.co.argo21.nautica.workflow.wfmc.WorkflowEngineHandler#assignActivityAttribute(java.lang.String, java.lang.String, java.lang.String, jp.co.argo21.nautica.workflow.wfmc.Attribute)
	 */
	public void assignActivityAttribute(String session,
			String pid, String aid, Attribute attr)
	throws InvalidSessionException, InvalidProcessInstanceException,
		InvalidActivityInstanceException, InvalidAttributeException,
		AttributeAssignmentFailedException
	{
		String argInfo = "(NAUTICA API = assignActivityAttribute,"
			 + "session = [" + session + "],"
			 + "pid = [" + pid + "],"
			 + "aid = [" + aid + "],"
			 + "attr = [" + attr + "])";

		try {
			checkProcessID(pid);
			checkActivityID(aid);

			if (attr == null) {
				// プロセス変数が未設定です。
				String E0131 = StringManager.get("E0131");
				throw new InvalidAttributeException(E0131);
			}
		
			DataAccessManager.begin(false);
				
			validateSession(session);

			ProcessManagerFactory pmf = ProcessManagerFactory.getInstance();
			WfProcessManager pm = pmf.getOwnerProcessManager(pid);
			WfProcess process = pm.getProcess(pid);
			WfActivity activity = process.getStep(aid);
			if (activity == null) {
				// 該当するアクティビティが存在しません。
				String msg = StringManager.get("E0069");
				throw new InvalidActivityInstanceException(msg);
			}
			activity.setContext(attr);
				
			DataAccessManager.commit();
				
			// 監査ログ出力
		    AuditDataRecord data = new AuditDataRecord(
		            new AuditPrefix(pid, "WMAssignedActivityInstanceAttributes", session),
		            new AuditSuffix());
		    data.setDataElement("ActivityInstanceID", aid);
		    data.setDataElement("ActivityState",activity.getState());
		    data.setDataElement("AttributeName", attr.getName());
		    data.setDataElement("AttributeType", attr.getType());
		    data.setDataElement("NewAttributeValue", attr.getValue()); 
		    audit.info(data);
	
		} catch (InvalidSessionException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidProcessInstanceException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidActivityInstanceException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidAttributeException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (AttributeAssignmentFailedException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (Exception ex) {
			try { DataAccessManager.rollback(); } catch (Exception ex2) { /* Ignore */ }
			// アクティビティ指定のプロセス変数の設定に失敗しました。
			String E0158 = StringManager.get("E0158") + argInfo;
			eLog.error(E0158, ex);
			throw new InvalidAttributeException(E0158, ex);
		} finally {
			try { DataAccessManager.close(); } catch (Exception ex) { /* Ignore */ }
		}
	}

	/**
	 * プロセスインスタンス一覧の取得を行う。
	 * 利用可能なフィルターはNameFilter, StateFilter、GroupFilterとする。
	 *
	 * @param session セッションID
	 * @param filter 検索用フィルター
	 * @return プロセスの一覧
	 * @throws InvalidSessionException 指定されたセッションが無効の場合
	 * @throws InvalidFilterException 指定されたフィルターが有効でない場合
	 * @see jp.co.argo21.nautica.workflow.wfmc.WorkflowEngineHandler#getProcesses(java.lang.String, jp.co.argo21.nautica.workflow.wfmc.Filter)
	 */
	public Process[] getProcesses(String session, Filter filter)
	throws InvalidSessionException, InvalidFilterException
	{
		String argInfo = "(NAUTICA API = getProcesses,"
			 + "session = [" + session + "],"
			 + "filter = [" + filter + "])";

		try {
			DataAccessManager.begin(false);
			
			validateSession(session);

			ProcessManagerFactory pmf = ProcessManagerFactory.getInstance();
			Process[] procs = pmf.getProcesses(filter);
			
			DataAccessManager.commit();

			return procs;
		} catch (InvalidSessionException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidFilterException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (Exception ex) {
			try { DataAccessManager.rollback(); } catch (Exception ex2) { /* Ignore */ }
			// プロセス一覧の取得に失敗しました。
			String E0199 = StringManager.get("E0199");
			eLog.error(E0199, ex);
			throw new InvalidFilterException(E0199, ex);
		} finally {
			try { DataAccessManager.close(); } catch (Exception ex) { /* Ignore */ }
		}
	}

	/**
	 * プロセスインスタンスの取得を行う。
	 *
	 * @param session セッションID
	 * @param pid プロセスインスタンスID
	 * @return プロセスインスタンス
	 * @throws InvalidSessionException 指定されたセッションが無効の場合
	 * @throws InvalidProcessInstanceException プロセスインスタンスIDが有効でない場合
	 * @see jp.co.argo21.nautica.workflow.wfmc.WorkflowEngineHandler#getProcess(java.lang.String, java.lang.String)
	 */
	public Process getProcess(String session, String pid)
	throws InvalidSessionException, InvalidProcessInstanceException
	{
		String argInfo = "(NAUTICA API = getProcess,"
			 + "session = [" + session + "],"
			 + "pid = [" + pid + "])";

		try {
			checkProcessID(pid);
			
			DataAccessManager.begin(false);
				
			validateSession(session);
	
			ProcessManagerFactory pmf = ProcessManagerFactory.getInstance();
			WfProcessManager pm = pmf.getOwnerProcessManager(pid);
			ProcessInternal internal = (ProcessInternal)pm.getProcess(pid);
				
			DataAccessManager.commit();
	
			return internal.getBean();
		} catch (InvalidSessionException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidProcessInstanceException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (Exception ex) {
			try { DataAccessManager.rollback(); } catch (Exception ex2) { /* Ignore */ }
			// プロセスの取得に失敗しました。
			String E0151 = StringManager.get("E0151") + argInfo;
			eLog.error(E0151, ex);
			throw new InvalidProcessInstanceException(E0151, ex);
		} finally {
			try { DataAccessManager.close(); } catch (Exception ex) { /* Ignore */ }
		}
	}

	/**
	 * アクティビティインスタンス一覧の取得を行う。
	 * 利用可能なフィルターはAttributeFilter, StateFilter、GroupFilterとする。
	 *
	 * @param session セッションID
	 * @param filter 検索用フィルター
	 * @return アクティビティインスタンス一覧
	 * @throws InvalidSessionException 指定されたセッションが無効の場合
	 * @throws InvalidFilterException 指定されたフィルターが有効でない場合
	 * @see jp.co.argo21.nautica.workflow.wfmc.WorkflowEngineHandler#getActivities(java.lang.String, jp.co.argo21.nautica.workflow.wfmc.Filter)
	 */
	public Activity[] getActivities(String session, Filter filter)
	throws InvalidSessionException, InvalidFilterException
	{
		String argInfo = "(NAUTICA API = getActivities,"
			 + "session = [" + session + "],"
			 + "filter = [" + filter + "])";

		try {
			DataAccessManager.begin(false);
			
			validateSession(session);

			ProcessManagerFactory pmf = ProcessManagerFactory.getInstance();
			Activity[] acts = pmf.getActivities(filter);
			
			DataAccessManager.commit();

			return acts;
		} catch (InvalidSessionException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidFilterException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (Exception ex) {
			try { DataAccessManager.rollback(); } catch (Exception ex2) { /* Ignore */ }
			// アクティビティ一覧の取得に失敗しました。
			String E0202 = StringManager.get("E0202") + argInfo;
			eLog.error(E0202, ex);
			throw new InvalidFilterException(E0202, ex);
		} finally {
			try { DataAccessManager.close(); } catch (Exception ex) { /* Ignore */ }
		}
	}

	/**
	 * アクティビティインスタンス一覧の取得を行う。
	 * 利用可能なフィルターはAttributeFilter, StateFilter、GroupFilterとする。
	 * WfMC仕様ではpidはないが、これは誤りであろうと判断し、
	 * pidを引数に追加した。
	 *
	 * @param session セッションID
	 * @param pid プロセスインスタンスID
	 * @param filter 検索用フィルター
	 * @return アクティビティインスタンス一覧
	 * @throws InvalidSessionException 指定されたセッションが無効の場合
	 * @throws InvalidFilterException 指定されたフィルターが有効でない場合
	 * @see jp.co.argo21.nautica.workflow.wfmc.WorkflowEngineHandler#getActivities(java.lang.String, java.lang.String, jp.co.argo21.nautica.workflow.wfmc.Filter)
	 */
	public Activity[] getActivities(String session, String pid, Filter filter)
	throws InvalidSessionException, InvalidFilterException
	{
		String argInfo = "(NAUTICA API = getActivities,"
			 + "session = [" + session + "],"
			 + "pid = [" + pid + "],"
			 + "filter = [" + filter + "])";

		try {
			if (pid == null || pid.trim().equals("")) {
				// プロセスIDが未設定です。
				String E0189 = StringManager.get("E0189");
				throw new InvalidFilterException(E0189);
			}
		
			DataAccessManager.begin(false);
				
			validateSession(session);
	
			ProcessManagerFactory pmf = ProcessManagerFactory.getInstance();
			WfProcessManager pm = pmf.getOwnerProcessManager(pid);
			ProcessInternal process = (ProcessInternal)pm.getProcess(pid);
			Activity[] acts = process.getActivities(filter);
				
			DataAccessManager.commit();
	
			return acts;
		} catch (InvalidSessionException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidFilterException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (Exception ex) {
			try { DataAccessManager.rollback(); } catch (Exception ex2) { /* Ignore */ }
			// アクティビティ一覧の取得に失敗しました。
			String E0202 = StringManager.get("E0202") + argInfo;
			eLog.error(E0202, ex);
			throw new InvalidFilterException(E0202, ex);
		} finally {
			try { DataAccessManager.close(); } catch (Exception ex) { /* Ignore */ }
		}
	}

	/**
	 * アクティビティインスタンスの取得を行う。
	 *
	 * @param session セッションID
	 * @param pid プロセスインスタンスID
	 * @param aid アクティビティインスタンスID
	 * @return アクティビティインスタンス
	 * @throws InvalidSessionException 指定されたセッションが無効の場合
	 * @throws InvalidProcessInstanceException プロセスインスタンスIDが有効でない場合
	 * @throws InvalidActivityInstanceException アクティビティインスタンスIDが有効でない場合
	 * @see jp.co.argo21.nautica.workflow.wfmc.WorkflowEngineHandler#getActivity(java.lang.String, java.lang.String, java.lang.String)
	 */
	public Activity getActivity(String session, String pid, String aid)
	throws InvalidSessionException, InvalidProcessInstanceException,
		InvalidActivityInstanceException
	{
		String argInfo = "(NAUTICA API = getActivity,"
			 + "session = [" + session + "],"
			 + "pid = [" + pid + "],"
			 + "aid = [" + aid + "])";

		try {
			checkProcessID(pid);
			checkActivityID(aid);

			DataAccessManager.begin(false);
			
			validateSession(session);
	
			ProcessManagerFactory pmf = ProcessManagerFactory.getInstance();
			WfProcessManager pm = pmf.getOwnerProcessManager(pid);
			WfProcess proc = pm.getProcess(pid);
			ActivityInternal internal = (ActivityInternal)proc.getStep(aid);
			
			if (internal == null) {
				// アクティビティが存在しません。
				String E0203 = StringManager.get("E0203");
				throw new InvalidActivityInstanceException(E0203);
			}
			Activity bean = internal.getBean();

			DataAccessManager.commit();
	
			return bean;
		} catch (InvalidSessionException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidProcessInstanceException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (InvalidActivityInstanceException ex) {
			rollbackAndLogging(ex, argInfo);
			throw ex;
		} catch (Exception ex) {
			try { DataAccessManager.rollback(); } catch (Exception ex2) { /* Ignore */ }
			// アクティビティの取得に失敗しました。
			String E0124 = StringManager.get("E0124") + argInfo;
			eLog.error(E0124, ex);
			throw new InvalidActivityInstanceException(E0124, ex);
		} finally {
			try { DataAccessManager.close(); } catch (Exception ex) { /* Ignore */ }
		}
	}
	
	/**
	 * ロールバック処理とエラーログの出力を行う。
	 *
	 * @param ex 例外
	 * @param argInfo 引数情報
	 */
	private void rollbackAndLogging(Exception ex, String argInfo)
	{
		try { DataAccessManager.rollback(); } catch (Exception ex2) { /* Ignore */ }
		String msg = ex.getMessage() + argInfo;
		eLog.error(msg, ex);
	}

	/**
	 * プロセスIDを検証する。
	 *
	 * @param pid プロセスID
	 * @throws InvalidProcessInstanceException 無効なプロセスIDの場合
	 */
	private void checkProcessID(String pid)
	throws InvalidProcessInstanceException
	{
		if (pid == null || pid.trim().equals("")) {
			// プロセスIDが未設定です。
			String E0189 = StringManager.get("E0189");
			throw new InvalidProcessInstanceException(E0189);
		}
	}

	/**
	 * アクティビティIDを検証する。
	 *
	 * @param aid アクティビティID
	 * @throws InvalidActivityInstanceException 無効なアクティビティIDの場合
	 */
	private void checkActivityID(String aid)
	throws InvalidActivityInstanceException
	{
		if (aid == null || aid.trim().equals("")) {
			// アクティビティIDが未設定です。
			String E0197 = StringManager.get("E0197");
			throw new InvalidActivityInstanceException(E0197);
		}
	}
	
	/**
	 * セッションを検証する。
	 *
	 * @param session セッションID
	 * @throws InvalidSessionException 指定されたセッションが無効の場合
	 */
	private void validateSession(String session)
	throws InvalidSessionException
	{
		if (session == null || session.trim().equals("")) {
			// セッションIDが未設定です。
			String E0170 = StringManager.get("E0170");
			throw new InvalidSessionException(E0170);
		}

		SessionManagerFactory factory = SessionManagerFactory.getInstance();
		SessionManager manager = factory.getSessionManager();
		manager.validateSession(session);
	}

	@SuppressWarnings("unused")
	private ActivityDefinition findActivity(ProcessDefinition pd, String adid)
	throws Exception
	{
		List<ActivityDefinition> acts = pd.getActivities();
		
		ActivityDefinition ad = null;
		for (ActivityDefinition def : acts) {
			if (ad.getID().equals(adid)) {
				ad = def;
				break;
			}
		}
		
		if (ad == null) {
			// アクティビティ定義が存在しません。
			String E0204 = StringManager.get("E0204");
			throw new WorkflowException(E0204);
		}
		
		return ad;
	}
}
