package jp.co.argo21.nautica.workflow.management.gbean;

import javax.jms.QueueConnectionFactory;
import javax.sql.DataSource;

import jp.co.argo21.nautica.workflow.engine.DataAccessManager;
import jp.co.argo21.nautica.workflow.engine.InterWorkflowConnectorFactory;
import jp.co.argo21.nautica.workflow.engine.MessageBroker;
import jp.co.argo21.nautica.workflow.engine.ResourceManagerFactory;
import jp.co.argo21.nautica.workflow.engine.ResourceManagerFactorySource;
import jp.co.argo21.nautica.workflow.engine.WorkflowEngine;
import jp.co.argo21.nautica.workflow.util.GeronimoUtils;
import jp.co.argo21.nautica.workflow.wfmc.ConnectionFailedException;
import jp.co.argo21.nautica.workflow.wfmc.DefinitionRepository;
import jp.co.argo21.nautica.workflow.wfmc.InterWorkflowConnector;
import jp.co.argo21.nautica.workflow.wfmc.InvalidSessionException;
import jp.co.argo21.nautica.workflow.wfmc.WorkItemHandler;
import jp.co.argo21.nautica.workflow.wfmc.WorkflowAdminHandler;
import jp.co.argo21.nautica.workflow.wfmc.WorkflowEngineHandler;
import jp.co.argo21.nautica.workflow.wfmc.WorkflowServiceManager;

import org.apache.geronimo.gbean.GBeanInfo;
import org.apache.geronimo.gbean.GBeanInfoBuilder;
import org.apache.geronimo.gbean.GBeanLifecycle;

public class WorkflowServiceManagerGBean
implements GBeanLifecycle, WorkflowServiceManager, InterWorkflowConnectorFactory, ResourceManagerFactorySource
{
	public static GBeanInfo GBEAN_INFO;

	private String homeDirectory;
	private String adminKey;
	private WorkflowEngine engine;
	private String queueConnectionFactoryName;
	private String dataSourceName;
	private boolean xa;

	static {
		GBeanInfoBuilder builder =
			new GBeanInfoBuilder("WorkflowServiceManagerGBean", WorkflowServiceManagerGBean.class);
		builder.addAttribute("homeDirectory", String.class, true);
		builder.addAttribute("administrativeKey", String.class, true);
		builder.addAttribute("queueConnectionFactoryName", String.class, true);
		builder.addAttribute("dataSourceName", String.class, true);
		builder.addAttribute("xa", Boolean.class, true);
		GBEAN_INFO = builder.getBeanInfo();
	}

	public static GBeanInfo getGBeanInfo()
	{
		return GBEAN_INFO;
	}

	public void doStart() throws Exception
	{
		initializeMessageBroker();
		initializeDataAccessManager();
		engine = WorkflowEngine.getInstance();
		engine.start(adminKey, homeDirectory);
	}

	public void doStop() throws Exception
	{
		if (engine != null) {
			engine.stop(adminKey);
		}
	}

	public void doFail()
	{
	}

	public String getHomeDirectory()
	{
		return homeDirectory;
	}

	public void setHomeDirectory(String dir)
	{
		String baseDir = System.getProperty("org.apache.geronimo.base.dir");
		String separator = System.getProperty("file.separator");
		this.homeDirectory = baseDir + separator + dir;
	}

	public String getAdministrativeKey()
	{
		return adminKey;
	}

	public void setAdministrativeKey(String adminKey)
	{
		this.adminKey = adminKey;
	}

	public String getQueueConnectionFactoryName()
	{
		return queueConnectionFactoryName;
	}

	public void setQueueConnectionFactoryName(String queueConnectionFactoryName)
	{
		this.queueConnectionFactoryName = queueConnectionFactoryName;
	}

	public String getDataSourceName()
	{
		return dataSourceName;
	}

	public void setDataSourceName(String dataSourceName)
	{
		this.dataSourceName = dataSourceName;
	}

	public Boolean isXa()
	{
		return xa;
	}

	public void setXa(Boolean xa)
	{
		this.xa = xa;
	}

	/**
	 * ワークフローエンジンへの接続認証を行い、
	 * セッションIDを取得する。
	 *
	 * @param user ユーザID
	 * @param pass パスワード
	 * @return セッションID
	 * @throws ConnectionFailedException 接続認証に失敗した場合
	 * @see jp.co.argo21.nautica.workflow.wfmc.WorkflowServiceManager#connect(java.lang.String, java.lang.String)
	 */
	@Override
	public String connect(String user, String pass)
	throws ConnectionFailedException
	{
		return engine.connect(user, pass);
	}

	/**
	 * ワークフローエンジンとの切断を行う。
	 *
	 * @param session セッションID
	 * @throws InvalidSessionException 指定されたセッションが無効の場合
	 * @see jp.co.argo21.nautica.workflow.wfmc.WorkflowServiceManager#disconnect(java.lang.String)
	 */
	@Override
	public void disconnect(String session)
	throws InvalidSessionException
	{
		engine.disconnect(session);
	}

	/**
	 * 定義リポジトリを返す。
	 *
	 * @param session セッションID
	 * @return 定義リポジトリ
	 * @throws InvalidSessionException 指定されたセッションが無効の場合
	 * @see jp.co.argo21.nautica.workflow.wfmc.WorkflowServiceManager#getDefinitionRepository(java.lang.String)
	 */
	@Override
	public DefinitionRepository getDefinitionRepository(String session)
	throws InvalidSessionException
	{
		return engine.getDefinitionRepository(session);
	}

	/**
	 * 作業項目ハンドラを返す。
	 *
	 * @param session セッションID
	 * @return 作業項目ハンドラ
	 * @throws InvalidSessionException 指定されたセッションが無効の場合
	 * @see jp.co.argo21.nautica.workflow.wfmc.WorkflowServiceManager#getWorkItemHandler(java.lang.String)
	 */
	@Override
	public WorkItemHandler getWorkItemHandler(String session)
	throws InvalidSessionException
	{
		return engine.getWorkItemHandler(session);
	}

	/**
	 * ワークフローエンジンハンドラを返す。
	 *
	 * @param session セッションID
	 * @return ワークフローエンジンハンドラ
	 * @throws InvalidSessionException 指定されたセッションが無効の場合
	 * @see jp.co.argo21.nautica.workflow.wfmc.WorkflowServiceManager#getWorkflowEngineHandler(java.lang.String)
	 */
	@Override
	public WorkflowEngineHandler getWorkflowEngineHandler(String session)
	throws InvalidSessionException
	{
		return engine.getWorkflowEngineHandler(session);
	}

	/**
	 * ワークフロー管理ハンドラを返す。
	 *
	 * @param session セッションID
	 * @return ワークフロー管理ハンドラ
	 * @throws InvalidSessionException 指定されたセッションが無効の場合
	 * @see jp.co.argo21.nautica.workflow.wfmc.WorkflowServiceManager#getWorkflowAdminHandler(java.lang.String)
	 */
	@Override
	public WorkflowAdminHandler getWorkflowAdminHandler(String session)
	throws InvalidSessionException
	{
		return engine.getWorkflowAdminHandler(session);
	}

	/**
	 * 
	 *
	 * @return
	 * @see jp.co.argo21.nautica.workflow.engine.InterWorkflowConnectorFactory#getInterWorkflowConnector()
	 */
	@Override
	public InterWorkflowConnector getInterWorkflowConnector()
	{
		return engine.getInterWorkflowConnector();
	}

	@Override
	public ResourceManagerFactory getResourceManagerFactory()
	{
		return engine.getResourceManagerFactory();
	}

	private void initializeMessageBroker() throws Exception
	{
		QueueConnectionFactory factory = 
			(QueueConnectionFactory)GeronimoUtils.getConnectionFactory(queueConnectionFactoryName);
		MessageBroker.initializeConnectionFactory(factory);
	}

	private void initializeDataAccessManager() throws Exception
	{
		DataSource ds =
			(DataSource)GeronimoUtils.getConnectionFactory(dataSourceName);
		DataAccessManager.setDataSource(ds, xa);
	}
}
