/* $Id: MySQLActivityDAO.java,v 1.1 2007/10/29 02:55:36 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.dataaccess.mysql;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import jp.co.argo21.nautica.workflow.dataaccess.AbstractDAO;
import jp.co.argo21.nautica.workflow.dataaccess.ActivityHistoryBean;
import jp.co.argo21.nautica.workflow.dataaccess.ActivityHistoryDAO;
import jp.co.argo21.nautica.workflow.dataaccess.DAOException;
import jp.co.argo21.nautica.workflow.dataaccess.ActivityBean;
import jp.co.argo21.nautica.workflow.dataaccess.ActivityDAO;
import jp.co.argo21.nautica.workflow.dataaccess.WorkflowDAOFactory;
import jp.co.argo21.nautica.workflow.engine.DataAccessManager;
import jp.co.argo21.nautica.workflow.engine.LogManager;
import jp.co.argo21.nautica.workflow.util.StringManager;
import jp.co.argo21.nautica.workflow.wfmc.ActivityState;
import jp.co.argo21.nautica.workflow.wfmc.Filter;
import jp.co.argo21.nautica.workflow.wfmc.InvalidFilterException;

/**
 * ActivityBeanをデータとするMySQL用DAOクラスである。
 * <pre><tt>
 * ACTIVITYテーブル
 * +----------------+-------------+------+-----+---------------------+-------+
 * | Field          | Type        | Null | Key | Default             | Extra |
 * +----------------+-------------+------+-----+---------------------+-------+
 * | PROC_ID        | varchar(64) |      | PRI |                     |       |
 * | ACT_ID         | varchar(64) |      | PRI |                     |       |
 * | ACT_DEF_ID     | varchar(64) |      |     |                     |       |
 * | START_DATE     | datetime    |      |     | 0000-00-00 00:00:00 |       |
 * | STARTER_ID     | varchar(64) |      |     |                     |       |
 * | DURATION_LIMIT | datetime    |      |     | 0000-00-00 00:00:00 |       |
 * | BLOCK_ID       | varchar(64) | YES  |     | NULL                |       |
 * | ACT_STATE      | int(1)      |      |     | 0                   |       |
 * | ACTOR_ID       | varchar(64) | YES  |     | NULL                |       |
 * | UPDATE_DATE    | datetime    | YES  |     | NULL                |       |
 * +----------------+-------------+------+-----+---------------------+-------+
 * </tt></pre>
 *
 * @author  nito(Argo 21, Corp.)
 * @version $Revision: 1.1 $
 * @since   Nautica Workflow 1.0
 */
public class MySQLActivityDAO extends AbstractDAO implements ActivityDAO
{
	/** エンジンログ */
	protected static Logger eLog = LogManager.getEngineLogger();

	/** プロセスIDのカラム名 */
	public static final String PROC_ID        = "PROC_ID";
	/** アクティビティIDのカラム名 */
	public static final String ACT_ID         = "ACT_ID";
	/** アクティビティ定義IDのカラム名 */
	public static final String ACT_DEF_ID     = "ACT_DEF_ID";
	/** 開始時間のカラム名 */
	public static final String START_DATE     = "START_DATE";
	/** アクティビティ開始者のカラム名 */
	public static final String STARTER_ID     = "STARTER_ID";
	/** 実行期限のカラム名 */
	public static final String DURATION_LIMIT = "DURATION_LIMIT";
	/** ブロックIDのカラム名 */
	public static final String BLOCK_ID       = "BLOCK_ID";
	/** アクティビティ状態のカラム名 */
	public static final String ACT_STATE      = "ACT_STATE";
	/** アクターIDのカラム名 */
	public static final String ACTOR_ID       = "ACTOR_ID";
	/** 更新日時のカラム名 */
	public static final String UPDATE_DATE    = "UPDATE_DATE";

	private static final String SQL_SELECT_BY_PRIMARY_KEY
	= "select * from ACTIVITY where PROC_ID = ? AND ACT_ID = ?";

	//まだブロック内で閉じていないアクティビティを探す
	private static final String SQL_SELECT_COUNT_OPEN_BY_BLOCK_ID
	= "select COUNT(*) from ACTIVITY where PROC_ID = ? AND BLOCK_ID = ? AND ACT_STATE < 4 ";

	//まだプロセス内で閉じていないアクティビティを探す
	private static final String SQL_SELECT_COUNT_OPEN_BY_PROC_ID
	= "select COUNT(*) from ACTIVITY where PROC_ID = ? AND ACT_STATE < 4 ";

	//まだプロセス内で閉じていないアクティビティを探す
	private static final String SQL_SELECT_OPEN_BY_PROC_ID
	= "select * from ACTIVITY where PROC_ID = ? AND ACT_STATE < 4 ";

	//同期終了アクティビティを探す
	private static final String SQL_SELECT_CONCUREND
	= "select * from ACTIVITY where PROC_ID = ? AND ACT_DEF_ID = ? AND BLOCK_ID = ? ";

	//アクティビティを探す
	private static final String SQL_SELECT_WITH_VAR
	= "select distinct a.* from ACTIVITY a, VARIABLE v ";

	//アクティビティを探す
	private static final String SQL_SELECT
	= "select distinct a.* from ACTIVITY a ";

	//アクティビティを探す
	private static final String SQL_SELECT_PDID_WITH_VAR
	= "select distinct a.* from PROCESS p, ACTIVITY a, VARIABLE v ";

	//アクティビティを探す
	private static final String SQL_SELECT_PDID
	= "select distinct a.* from PROCESS p, ACTIVITY a ";

	private static final String SQL_INSERT
	= "insert into ACTIVITY ("
		+ PROC_ID + ", "
		+ ACT_ID + ", "
		+ ACT_DEF_ID + ", "
		+ START_DATE + ", "
		+ STARTER_ID + ", "
		+ DURATION_LIMIT + ", "
		+ BLOCK_ID + ", "
		+ ACT_STATE + ", "
		+ ACTOR_ID + ", "
		+ UPDATE_DATE + ") values (?,?,?,?,?,?,?,?,?,?)";

	private static final String SQL_UPDATE_STATE
	= "UPDATE ACTIVITY SET ACT_STATE = ?, UPDATE_DATE = ? WHERE ACT_ID = ? ";

	private static final String SQL_UPDATE_DATE
	= "UPDATE ACTIVITY SET UPDATE_DATE = ? WHERE ACT_ID = ? ";

	private static final String SQL_UPDATE_BLOCK_ID
	= "UPDATE ACTIVITY SET BLOCK_ID = ? WHERE ACT_ID = ? ";
	
	/**
	 * プロセス管理テーブルに対するアクセスオブジェクトを生成する。
	 *
	 * @param conn コネクション
	 */
	MySQLActivityDAO(Connection conn)
	{
		super(conn);
	}
	
	/**
	 * 主キーにより、ActivityBeanを取得する。
	 *
	 * @param pid プロセスID
	 * @param aid アクティビティID
	 * @return アクティビティ
	 * @throws SQLException 任意のSQL例外
	 * @throws DAOException DAO実行中に処理としてあげる場合がある例外
	 * @see jp.co.argo21.nautica.workflow.dataaccess.ActivityDAO#findByPrimaryKey(java.lang.String, java.lang.String)
	 */
	public ActivityBean findByPrimaryKey(String pid, String aid)
	throws SQLException, DAOException
	{
		PreparedStatement st = getConnection().prepareStatement(SQL_SELECT_BY_PRIMARY_KEY);
		try {
			st.setString(1, pid);
			st.setString(2, aid);

			/************** DEBUG **************/
			eLog.debug(st.toString());
			/***********************************/

			ResultSet rs = st.executeQuery();
			
			ActivityBean bean = null;
			if (rs.next()) {
				bean = createBean(rs);
			}
			return bean;
		} finally {
			st.close();
		}
	}
	
	/**
	 * プロセス内で指定されたブロックIDを持ち、実行中のアクティビティの個数を返す。
	 *
	 * @param pid プロセスID
	 * @param bid ブロックID
	 * @return アクティビティの個数
	 * @throws SQLException 任意のSQL例外
	 * @throws DAOException DAO実行中に処理としてあげる場合がある例外
	 * @see jp.co.argo21.nautica.workflow.dataaccess.ActivityDAO#findOpeningActivityCountByBlockID(java.lang.String, java.lang.String)
	 */
	public int findOpeningActivityCountByBlockID(String pid, String bid)
	throws SQLException, DAOException
	{
		PreparedStatement st = getConnection().prepareStatement(SQL_SELECT_COUNT_OPEN_BY_BLOCK_ID);
		try {
			st.setString(1, pid);
			st.setString(2, bid);

			/************** DEBUG **************/
			eLog.debug(st.toString());
			/***********************************/
			
			ResultSet rs = st.executeQuery();
			
			int count = 0;
			if (rs.next()) {
				count = rs.getInt(1);
			}
			return count;
		} finally {
			st.close();
		}
	}

	/**
	 * プロセス内のアクティビティの個数を返す。
	 *
	 * @param pid プロセスID
	 * @return アクティビティの個数
	 * @throws SQLException 任意のSQL例外
	 * @throws DAOException DAO実行中に処理としてあげる場合がある例外
	 * @see jp.co.argo21.nautica.workflow.dataaccess.ActivityDAO#findOpeningActivityCountByProcessID(java.lang.String)
	 */
	public int findOpeningActivityCountByProcessID(String pid)
	throws SQLException, DAOException
	{
		PreparedStatement st = getConnection().prepareStatement(SQL_SELECT_COUNT_OPEN_BY_PROC_ID);
		try {
			st.setString(1, pid);

			/************** DEBUG **************/
			eLog.debug(st.toString());
			/***********************************/
			
			ResultSet rs = st.executeQuery();
			
			int count = 0;
			if (rs.next()) {
				count = rs.getInt(1);
			}
			return count;
		} finally {
			st.close();
		}
	}

	/**
	 * プロセス内のアクティビティを返す。
	 *
	 * @param pid プロセスID
	 * @return アクティビティ
	 * @throws SQLException 任意のSQL例外
	 * @throws DAOException DAO実行中に処理としてあげる場合がある例外
	 * @see jp.co.argo21.nautica.workflow.dataaccess.ActivityDAO#findOpeningActivityByProcessID(java.lang.String)
	 */
	public ActivityBean[] findOpeningActivityByProcessID(String pid)
	throws SQLException, DAOException
	{
		PreparedStatement st = getConnection().prepareStatement(SQL_SELECT_OPEN_BY_PROC_ID);
		try {
			st.setString(1, pid);

			/************** DEBUG **************/
			eLog.debug(st.toString());
			/***********************************/
			
			ResultSet rs = st.executeQuery();
			
			List<ActivityBean> list = new ArrayList<ActivityBean>();
			while (rs.next()) {
				ActivityBean bean = createBean(rs);
				list.add(bean);
			}
			return (ActivityBean[])list.toArray(new ActivityBean[list.size()]);
		} finally {
			st.close();
		}
	}

	/**
	 * ブロックIDに対応するブロックの並行処理終了アクティビティを取得する。
	 *
	 * @param pid プロセスID
	 * @param adid アクティビティ定義ID
	 * @param bid ブロックID
	 * @return アクティビティ
	 * @throws SQLException 任意のSQL例外
	 * @throws DAOException DAO実行中に処理としてあげる場合がある例外
	 * @see jp.co.argo21.nautica.workflow.dataaccess.ActivityDAO#findConcurrentEnd(java.lang.String, java.lang.String, java.lang.String)
	 */
	public ActivityBean findConcurrentEnd(String pid, String adid, String bid)
	throws SQLException, DAOException
	{
		PreparedStatement st = getConnection().prepareStatement(SQL_SELECT_CONCUREND);
		try {
			st.setString(1, pid);
			st.setString(2, adid);
			st.setString(3, bid);

			/************** DEBUG **************/
			eLog.debug(st.toString());
			/***********************************/
			
			ResultSet rs = st.executeQuery();
			
			ActivityBean bean = null;
			if (rs.next()) {
				bean = createBean(rs);
			}
			return bean;
		} finally {
			st.close();
		}
	}

	/**
	 * 指定されたフィルターで特定されるアクティビティを返す。
	 *
	 * @param filter フィルター
	 * @return アクティビティ
	 * @throws SQLException 任意のSQL例外
	 * @throws DAOException DAO実行中に処理としてあげる場合がある例外
	 * @throws InvalidFilterException 無効なフィルターが指定された場合
	 * @see jp.co.argo21.nautica.workflow.dataaccess.ActivityDAO#findByFilter(jp.co.argo21.nautica.workflow.wfmc.Filter)
	 */
	public ActivityBean[] findByFilter(Filter filter)
	throws SQLException, DAOException, InvalidFilterException
	{
		ActivityFilterConverter converter = new ActivityFilterConverter();
		String where = converter.convertToSQL(filter);
		
		if (where.equals("") == false) {
			where = " where " + where;
		}

		String sqlSelect = null;
		if (converter.hasAttributeFilter()) {
			sqlSelect = SQL_SELECT_WITH_VAR;
		} else {
			sqlSelect = SQL_SELECT;
		}
		PreparedStatement st = getConnection().prepareStatement(sqlSelect + where);

		/************** DEBUG **************/
		eLog.debug(st.toString());
		/***********************************/
		try {
			ResultSet rs = st.executeQuery();
			
			List<ActivityBean> list = new ArrayList<ActivityBean>();
			while (rs.next()) {
				ActivityBean bean = createBean(rs);
				list.add(bean);
			}
			return (ActivityBean[])list.toArray(new ActivityBean[list.size()]);
		} finally {
			st.close();
		}
	}

	/**
	 * 指定されたプロセスとフィルターで特定されるアクティビティを返す。
	 *
	 * @param pid プロセスID
	 * @param filter フィルター
	 * @return アクティビティ
	 * @throws SQLException 任意のSQL例外
	 * @throws DAOException DAO実行中に処理としてあげる場合がある例外
	 * @throws InvalidFilterException 無効なフィルターが指定された場合
	 * @see jp.co.argo21.nautica.workflow.dataaccess.ActivityDAO#findByFilter(java.lang.String, jp.co.argo21.nautica.workflow.wfmc.Filter)
	 */
	public ActivityBean[] findByFilter(String pid, Filter filter)
	throws SQLException, DAOException, InvalidFilterException
	{
		ActivityFilterConverter converter = new ActivityFilterConverter();
		String where = converter.convertToSQL(filter);
		

		if (pid == null) {
			// 無効なフィルターが指定されました。
			String errMsg = StringManager.get("E0004");
			throw new InvalidFilterException(errMsg);
		}

		if (where.equals("")) {
			where = " where a.PROC_ID = '" + pid + "' ";
		} else {
			where = " where " + where + " AND a.PROC_ID = '" + pid + "' ";
		}

		String sqlSelect = null;
		if (converter.hasAttributeFilter()) {
			sqlSelect = SQL_SELECT_WITH_VAR;
		} else {
			sqlSelect = SQL_SELECT;
		}
		PreparedStatement st = getConnection().prepareStatement(sqlSelect + where);

		/************** DEBUG **************/
		eLog.debug(st.toString());
		/***********************************/
		try {
			ResultSet rs = st.executeQuery();
			
			List<ActivityBean> list = new ArrayList<ActivityBean>();
			while (rs.next()) {
				ActivityBean bean = createBean(rs);
				list.add(bean);
			}
			return (ActivityBean[])list.toArray(new ActivityBean[list.size()]);
		} finally {
			st.close();
		}
	}

	/**
	 * 指定された定義IDとフィルターで特定されるアクティビティを返す。
	 *
	 * @param pdid プロセス定義ID
	 * @param adid アクティビティ定義ID
	 * @param filter フィルター
	 * @return アクティビティ
	 * @throws SQLException 任意のSQL例外
	 * @throws DAOException DAO実行中に処理としてあげる場合がある例外
	 * @throws InvalidFilterException 無効なフィルターが指定された場合
	 * @see jp.co.argo21.nautica.workflow.dataaccess.ActivityDAO#findByFilter(java.lang.String, java.lang.String, jp.co.argo21.nautica.workflow.wfmc.Filter)
	 */
	public ActivityBean[] findByFilter(String pdid, String adid, Filter filter)
	throws SQLException, DAOException, InvalidFilterException
	{
		ActivityFilterConverter converter = new ActivityFilterConverter();
		String where = converter.convertToSQL(filter);
		
		if (where.equals("")) {
			where = " where p.PROC_DEF_ID = '" + pdid + "' "
			      + "and p.PROC_ID = a.PROC_ID and a.ACT_DEF_ID = '" + adid + "' ";
		} else {
			where = " where p.PROC_DEF_ID = '" + pdid + "' "
		      + "and p.PROC_ID = a.PROC_ID and a.ACT_DEF_ID = '" + adid + "' and " + where;
		}

		String sqlSelect = null;
		if (converter.hasAttributeFilter()) {
			sqlSelect = SQL_SELECT_PDID_WITH_VAR;
		} else {
			sqlSelect = SQL_SELECT_PDID;
		}
		PreparedStatement st = getConnection().prepareStatement(sqlSelect + where);

		/************** DEBUG **************/
		eLog.debug(st.toString());
		/***********************************/
		try {
			ResultSet rs = st.executeQuery();
			
			List<ActivityBean> list = new ArrayList<ActivityBean>();
			while (rs.next()) {
				ActivityBean bean = createBean(rs);
				list.add(bean);
			}
			return (ActivityBean[])list.toArray(new ActivityBean[list.size()]);
		} finally {
			st.close();
		}
	}

	/**
	 * 指定されたアクティビティを挿入する。
	 *
	 * @param bean アクティビティ
	 * @throws SQLException 任意のSQL例外
	 * @throws DAOException DAO実行中に処理としてあげる場合がある例外
	 * @see jp.co.argo21.nautica.workflow.dataaccess.ActivityDAO#insert(jp.co.argo21.nautica.workflow.dataaccess.ActivityBean)
	 */
	public void insert(ActivityBean bean)
	throws SQLException, DAOException
	{
		PreparedStatement st = getConnection().prepareStatement(SQL_INSERT);
		try {
			st.setString(1, bean.getProcessID());
			st.setString(2, bean.getActivityID());
			st.setString(3, bean.getActivityDefinitionID());
			st.setTimestamp(4, bean.getStartDate());
			st.setString(5, bean.getStarterID());
			st.setTimestamp(6, bean.getDurationLimit());
			st.setString(7, bean.getBlockID());
			st.setInt(8, bean.getActivityState());
			st.setString(9, bean.getActorID());
			st.setTimestamp(10, bean.getUpdateDate());
			

			/************** DEBUG **************/
			eLog.debug(st.toString());
			/***********************************/
			int i = st.executeUpdate();
			
			if (i != 1) {
				// アクティビティレコードの挿入に失敗しました。
				String errMsg = StringManager.get("E0007");
				throw new DAOException(errMsg);
			}
		} finally {
			st.close();
		}

		try {
			WorkflowDAOFactory factory = DataAccessManager.getDAOFactory();
			ActivityHistoryDAO ahDAO = factory.getActivityHistoryDAO();
			ActivityHistoryBean history = new ActivityHistoryBean();
			history.setProcID(bean.getProcessID());
			history.setActID(bean.getActivityID());
			history.setActDefID(bean.getActivityDefinitionID());
			history.setActorID(bean.getActorID());
			history.setPrevState(-1);
			history.setNewState(bean.getActivityState());
			history.setUpdateDate(bean.getUpdateDate());
			history.setReason("NEW ACTIVITY CREATION");
			ahDAO.insert(history);
		} catch (SQLException ex) {
			throw ex;
		} catch (DAOException ex) {
			throw ex;
		} catch (Exception ex) {
			// アクティビティ状態履歴レコードの挿入に失敗しました。
			String errMsg = StringManager.get("E0008");
			throw new DAOException(errMsg);
		}
	}
	
	/**
	 * アクティビティの状態を更新する
	 *
	 * @param bean アクティビティ
	 * @param state アクティビティ状態
	 * @param ts タイムスタンプ
	 * @throws SQLException 任意のSQL例外
	 * @throws DAOException DAO実行中に処理としてあげる場合がある例外
	 * @see jp.co.argo21.nautica.workflow.dataaccess.ActivityDAO#updateState(jp.co.argo21.nautica.workflow.dataaccess.ActivityBean, jp.co.argo21.nautica.workflow.wfmc.ActivityState, java.sql.Timestamp)
	 */
	public void updateState(ActivityBean bean, ActivityState state, Timestamp ts)
	throws SQLException, DAOException
	{
		PreparedStatement st = getConnection().prepareStatement(SQL_UPDATE_STATE);
		try {
			st.setInt(1, state.toInt());
			st.setTimestamp(2, ts);
			st.setString(3, bean.getActivityID());
			

			/************** DEBUG **************/
			eLog.debug(st.toString());
			/***********************************/
			int i = st.executeUpdate();
			
			if (i != 1) {
				// アクティビティレコードの更新に失敗しました。
				String errMsg = StringManager.get("E0010");
				throw new DAOException(errMsg);
			}
		} finally {
			st.close();
		}

		try {
			WorkflowDAOFactory factory = DataAccessManager.getDAOFactory();
			ActivityHistoryDAO ahDAO = factory.getActivityHistoryDAO();
			ActivityHistoryBean history = new ActivityHistoryBean();
			history.setProcID(bean.getProcessID());
			history.setActID(bean.getActivityID());
			history.setActDefID(bean.getActivityDefinitionID());
			history.setActorID(bean.getActorID());
			history.setPrevState(bean.getActivityState());
			history.setNewState(state.toInt());
			history.setUpdateDate(bean.getUpdateDate());
			ActivityState old = ActivityState.getState(bean.getActivityState());
			String msg = "ACTIVITY STATE CHANGED FROM " + old.toString() + " TO " + state.toString();
			history.setReason(msg);
			ahDAO.insert(history);
		} catch (SQLException ex) {
			throw ex;
		} catch (DAOException ex) {
			throw ex;
		} catch (Exception ex) {
			// アクティビティ状態履歴レコードの更新に失敗しました。
			String errMsg = StringManager.get("E0011");
			throw new DAOException(errMsg);
		}
		bean.setUpdateDate(ts);
		bean.setActivityState(state.toInt());
	}

	/**
	 * 更新日付を更新する。
	 *
	 * @param bean アクティビティ
	 * @param ts タイムスタンプ
	 * @throws SQLException 任意のSQL例外
	 * @throws DAOException DAO実行中に処理としてあげる場合がある例外
	 * @see jp.co.argo21.nautica.workflow.dataaccess.ActivityDAO#updateDate(jp.co.argo21.nautica.workflow.dataaccess.ActivityBean, java.sql.Timestamp)
	 */
	public void updateDate(ActivityBean bean, Timestamp ts)
	throws SQLException, DAOException
	{
		PreparedStatement st = getConnection().prepareStatement(SQL_UPDATE_DATE);
		try {
			st.setTimestamp(1, ts);
			st.setString(2, bean.getActivityID());
			

			/************** DEBUG **************/
			eLog.debug(st.toString());
			/***********************************/
			int i = st.executeUpdate();
			
			if (i != 1) {
				// アクティビティレコードの更新に失敗しました。
				String errMsg = StringManager.get("E0010");
				throw new DAOException(errMsg);
			}
		} finally {
			st.close();
		}

		try {
			ActivityState old = ActivityState.getState(bean.getActivityState());
			WorkflowDAOFactory factory = DataAccessManager.getDAOFactory();
			ActivityHistoryDAO ahDAO = factory.getActivityHistoryDAO();
			ActivityHistoryBean history = new ActivityHistoryBean();
			history.setProcID(bean.getProcessID());
			history.setActID(bean.getActivityID());
			history.setActDefID(bean.getActivityDefinitionID());
			history.setActorID(bean.getActorID());
			history.setPrevState(bean.getActivityState());
			history.setNewState(old.toInt());
			history.setUpdateDate(bean.getUpdateDate());
			String msg = "PROCESS STATE NOTIFIED FROM " + old.toString();
			history.setReason(msg);
			ahDAO.insert(history);
		} catch (SQLException ex) {
			throw ex;
		} catch (DAOException ex) {
			throw ex;
		} catch (Exception ex) {
			// アクティビティ状態履歴レコードの更新に失敗しました。
			String errMsg = StringManager.get("E0011");
			throw new DAOException(errMsg);
		}
		bean.setUpdateDate(ts);
	}

	/**
	 * ブロックIDを更新する。
	 *
	 * @param bean アクティビティ
	 * @param bid ブロックID
	 * @throws SQLException 任意のSQL例外
	 * @throws DAOException DAO実行中に処理としてあげる場合がある例外
	 * @see jp.co.argo21.nautica.workflow.dataaccess.ActivityDAO#updateBlockID(jp.co.argo21.nautica.workflow.dataaccess.ActivityBean, java.lang.String)
	 */
	public void updateBlockID(ActivityBean bean, String bid)
	throws SQLException, DAOException
	{
		PreparedStatement st = getConnection().prepareStatement(SQL_UPDATE_BLOCK_ID);
		try {
			st.setString(1, bid);
			st.setString(2, bean.getActivityID());
			

			/************** DEBUG **************/
			eLog.debug(st.toString());
			/***********************************/
			int i = st.executeUpdate();
			
			if (i != 1) {
				// アクティビティのブロックIDの更新に失敗しました。
				String errMsg = StringManager.get("E0009");
				throw new DAOException(errMsg);
			}
			bean.setBlockID(bid);
		} finally {
			st.close();
		}
	}
	
	/**
	 * 結果セットからアクティビティを生成する。
	 *
	 * @param rs 結果セット
	 * @return アクティビティ
	 * @throws SQLException 任意のSQL例外
	 */
	private ActivityBean createBean(ResultSet rs)
	throws SQLException
	{
		ActivityBean bean = new ActivityBean();

		bean.setProcessID(rs.getString(PROC_ID));
		bean.setActivityID(rs.getString(ACT_ID));
		bean.setActivityDefinitionID(rs.getString(ACT_DEF_ID));
		bean.setStartDate(rs.getTimestamp(START_DATE));
		bean.setStarterID(rs.getString(STARTER_ID));
		bean.setDurationLimit(rs.getTimestamp(DURATION_LIMIT));
		bean.setBlockID(rs.getString(BLOCK_ID));
		bean.setActivityState(rs.getInt(ACT_STATE));
		bean.setActorID(rs.getString(ACTOR_ID));
		bean.setUpdateDate(rs.getTimestamp(UPDATE_DATE));
		
		return bean;
	}
}
