//----------------------------BEGIN LICENSE----------------------------
/* 
 * Willow : the Open Source WorkFlow Project
 * Distributable under GNU LGPL license by gun.org
 *
 * Copyright (C) 2004-2010 huihoo.org 
 * Copyright (C) 2004-2010  ZosaTapo <dertyang@hotmail.com> 
 * 
 * ====================================================================
 * Project Homepage : http://www.huihoo.org/willow
 * Source Forge     : http://sourceforge.net/projects/huihoo
 * Mailing list     : willow@lists.sourceforge.net 
 */
//----------------------------END  LICENSE----------------------------

package org.huihoo.workflow.event;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import org.huihoo.workflow.SchemaContext;
import org.huihoo.workflow.TransactionException;
import org.huihoo.workflow.WorkflowException;
import org.huihoo.workflow.WorkflowTransaction;
import org.huihoo.workflow.server.WorkflowCase;
import org.huihoo.workflow.server.WorkflowWork;
import org.huihoo.workflow.server.WorkflowXPDL;
import org.huihoo.workflow.server.WorkflowSession;
import org.huihoo.workflow.store.WorkflowCaseDatabase;
import org.huihoo.workflow.usermodel.WorkflowParticipant;
import org.huihoo.workflow.util.WorkflowParticipantSelector;
import org.huihoo.workflow.xpdl.ExtendedAttribute;
import org.huihoo.workflow.xpdl.WorkflowActivity;
import org.huihoo.workflow.xpdl.WorkflowProcess;
import org.huihoo.workflow.xpdl.WorkflowTransition;
import org.huihoo.workflow.xpdl.XPDLGlobals;
import org.huihoo.workflow.xpdl.activity.JoinType;

import org.huihoo.commons.jdbc.JDBCUtilities;

public class JoinEventDispatcher
{
	//-------------------------------------------------------------------
	//
	//-------------------------------------------------------------------
	public static JoinEventGuard eventDispatch(
		WorkflowSession workflowsession,
		WorkflowXPDL workflowtemplate,
		WorkflowTransaction eventTransaction,
		WorkflowTransition workflowTransition,
		WorkflowProcess workflowProcess,
		WorkflowWork work,
		Map userObject)
	{
		WorkflowActivity joinActivity = workflowTransition.getToActivity();
		JoinType joinType = joinActivity.getJoinType();
		if (joinType != null)
		{
			WorkflowTransaction userTransaction = null;
			JoinEventGuard eventResult = null;
			try
			{
				userTransaction = workflowtemplate.getWorkflowTemplate().getCaseDatabase().getWorkflowTransaction();

				if (JoinType.JOIN_AND.equals(joinType))
				{
					eventResult =
						JoinEventDispatcher.submit_andJoin(
							workflowsession,
							workflowtemplate,
							eventTransaction,
							userTransaction,
							workflowProcess,
							work,
							workflowTransition,
							userObject);
				}

				else if (JoinType.JOIN_XOR.equals(joinType))
				{
					eventResult =
						JoinEventDispatcher.submit_xorJoin(
							workflowsession,
							workflowtemplate,
							eventTransaction,
							userTransaction,
							workflowProcess,
							work,
							workflowTransition,
							userObject);
				}

				else if (JoinType.JOIN_OR.equals(joinType))
				{
					eventResult =
						JoinEventDispatcher.submit_orJoin(
							workflowsession,
							workflowtemplate,
							eventTransaction,
							userTransaction,
							workflowProcess,
							work,
							workflowTransition,
							userObject);
				}

				else if (JoinType.JOIN_WEIGHT.equals(joinType))
				{
					eventResult =
						JoinEventDispatcher.submit_weightJoin(
							workflowsession,
							workflowtemplate,
							eventTransaction,
							userTransaction,
							workflowProcess,
							work,
							workflowTransition,
							userObject);
				}
				else if (JoinType.JOIN_INSTANCE_AND.equals(joinType))
				{
					eventResult =
						JoinEventDispatcher.submit_instanceAndJoin(
							workflowsession,
							workflowtemplate,
							eventTransaction,
							userTransaction,
							workflowProcess,
							work,
							workflowTransition,
							userObject);
				}
				else if (JoinType.JOIN_INSTANCE_XOR.equals(joinType))
				{
					eventResult =
						JoinEventDispatcher.submit_instanceXorJoin(
							workflowsession,
							workflowtemplate,
							eventTransaction,
							userTransaction,
							workflowProcess,
							work,
							workflowTransition,
							userObject);
				}
				else if (JoinType.JOIN_INSTANCE_WEIGHT.equals(joinType))
				{
					eventResult =
						JoinEventDispatcher.submit_instanceWeightJoin(
							workflowsession,
							workflowtemplate,
							eventTransaction,
							userTransaction,
							workflowProcess,
							work,
							workflowTransition,
							userObject);
				}
				else
				{
					throw new WorkflowException("JoinType '" + joinType + "' not supported by current realse");
				}
				userTransaction.commit();
			}
			catch (WorkflowException ex)
			{
				if (userTransaction != null)
				{
					try
					{
						userTransaction.rollback();
					}
					catch (TransactionException e)
					{
						e.printStackTrace();
					}
				}

				eventResult = new JoinEventGuard(work);
				eventResult.setJoinException(ex);
			}
			finally
			{
				if (userTransaction != null)
				{
					try
					{
						userTransaction.release();
					}
					catch (TransactionException e)
					{
						e.printStackTrace();
					}
				}
			}

			return eventResult;
		}

		JoinEventGuard eventResult = new JoinEventGuard(work);
		eventResult.setJoinException(new WorkflowException("JoinType " + joinType + " not supported by current realse"));
		return eventResult;
	}

	protected static JoinEventGuard submit_andJoin(
		WorkflowSession workflowsession,
		WorkflowXPDL workflowtemplate,
		WorkflowTransaction eventTransaction,
		WorkflowTransaction userTransaction,
		WorkflowProcess workflowProcess,
		WorkflowWork work,
		WorkflowTransition workflowTransition,
		Map userObject)
	{
		WorkflowCaseDatabase caseDatabase = workflowtemplate.getWorkflowTemplate().getCaseDatabase();

		WorkflowCase workflowCase = work.getCase();
		WorkflowActivity srcActivity = workflowTransition.getFromActivity();
		String src_owner_process_id = srcActivity.getWorkflowProcess().getUUID();
		String src_activity_id = srcActivity.getUUID();

		String packageId = workflowProcess.getWorkflowPackage().getUUID();
		String processId = workflowProcess.getUUID();
		String caseId = workflowCase.getUUID();

		WorkflowActivity joinActivity = workflowTransition.getToActivity();
		String join_owner_process_id = joinActivity.getWorkflowProcess().getUUID();
		String join_activity_id = joinActivity.getUUID();

		Connection conn = userTransaction.getConnection();
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		String strSQL = null;

		JoinEventGuard eventResult = new JoinEventGuard(work);

		try
		{
			//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
			int src_activity_dispatch_count = 0;

			//--------------------------------------------------------------------
			// DISP ACTIVITY DISPATCH INFO
			// 1. 取得本次分发的工作项所归属的活动节点信息
			//--------------------------------------------------------------------
			strSQL =
				"SELECT  int_dispatch_count,int_join_monitor  FROM "
					+ " "
					+ userTransaction.getDatabase().getSchemaContext().getTableName(SchemaContext.SCHEMA_ACTIVITY_DISPATCH)
					+ "  "
					+ "WHERE  vc_packageid=? "
					+ " "
					+ "AND    vc_processid=? "
					+ " "
					+ "AND    vc_caseid=?  "
					+ " "
					+ "AND    vc_owner_processid=? "
					+ " "
					+ "AND    vc_activityid=? ";

			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, packageId);
			pstmt.setString(2, processId);
			pstmt.setString(3, caseId);
			pstmt.setString(4, src_owner_process_id);
			pstmt.setString(5, src_activity_id);

			rs = pstmt.executeQuery();
			if (rs.next())
			{
				src_activity_dispatch_count = rs.getInt("int_dispatch_count");
			}

			eventResult.setDispatchCount(src_activity_dispatch_count);

			//--------------------------------------------------------------------
			// JOIN ACTIVITY DISPATCH INFO
			// 2.取得工作项即将汇聚的活动节点信息
			//--------------------------------------------------------------------
			int join_activity_monitor_count = 0;
			int join_activity_dispatch_count = 0;

			rs.close();

			pstmt.setString(1, packageId);
			pstmt.setString(2, processId);
			pstmt.setString(3, caseId);
			pstmt.setString(4, join_owner_process_id);
			pstmt.setString(5, join_activity_id);

			rs = pstmt.executeQuery();
			if (rs.next())
			{
				join_activity_dispatch_count = rs.getInt("int_dispatch_count");
				join_activity_monitor_count = rs.getInt("int_join_monitor");
			}

			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;

			if ((src_activity_dispatch_count + 1) < join_activity_dispatch_count)
			{
				eventResult.setFirst(false);
				eventResult.setLast(false);

				return eventResult;
			}

			//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++	
			// 3. 取得汇聚的活动节点当前完成的前继工作项信息
			//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
			String join_work_uuid = null;
			strSQL =
				"SELECT vc_uuid  FROM "
					+ " "
					+ caseDatabase.getSchemaContext().getTableName(SchemaContext.SCHEMA_WORK)
					+ " "
					+ "WHERE  dat_acceptTime IS NULL "
					+ " "
					+ "AND    vc_packageid=? "
					+ " "
					+ "AND    vc_processid=? "
					+ " "
					+ "AND    vc_caseid=?  "
					+ " "
					+ "AND    vc_owner_processid=? "
					+ " "
					+ "AND    vc_activityid=? ";

			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, packageId);
			pstmt.setString(2, processId);
			pstmt.setString(3, caseId);

			pstmt.setString(4, join_owner_process_id);
			pstmt.setString(5, join_activity_id);

			rs = pstmt.executeQuery();

			if (rs.next())
			{
				//汇聚已经触发,设置为中间工作项
				eventResult.setFirst(false);
				eventResult.setLast(false);
				join_work_uuid = rs.getString("vc_uuid");
			}
			else
			{
				//汇聚准备触发,设置为开始工作项
				eventResult.setFirst(true);
				eventResult.setLast(false);
				join_activity_monitor_count = 0;
			}

			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;

			List inTrans = joinActivity.getValidIncomingTransitions();
			int sizeTrans = inTrans.size();
			//			System.err.println("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
			//			System.err.println("joinActivity : "+joinActivity);
			//			System.err.println(inTrans);
			//			System.err.println("join_activity_monitor_count : "+join_activity_monitor_count);
			//			System.err.println("join_activity_dispatch_count : "+join_activity_dispatch_count);

			if ((join_activity_monitor_count + 1) >= sizeTrans)
			{
				//中间工作项符合结束工作项条件,设置为结束工作项
				eventResult.setLast(true);
			}

			if (join_activity_dispatch_count == 0)
			{
				strSQL =
					"INSERT INTO  "
						+ userTransaction.getDatabase().getSchemaContext().getTableName(SchemaContext.SCHEMA_ACTIVITY_DISPATCH)
						+ "(vc_packageid,vc_processid,vc_caseid,vc_owner_processid,vc_activityid,int_dispatch_count,int_join_monitor) "
						+ " VALUES(?,?,?,?,?,?,?)";
				pstmt = conn.prepareStatement(strSQL);
				pstmt.setString(1, packageId);
				pstmt.setString(2, processId);
				pstmt.setString(3, caseId);
				pstmt.setString(4, join_owner_process_id);
				pstmt.setString(5, join_activity_id);
				pstmt.setInt(6, join_activity_dispatch_count + 1); //i.e 1
				pstmt.setInt(7, join_activity_monitor_count + 1); //i.e 1
				pstmt.execute();

				JDBCUtilities.cleanupNoThrow(pstmt);
				pstmt = null;
			}
			else
			{
				if (eventResult.isFirst())
				{
					join_activity_dispatch_count += 1; //增加
				}

				strSQL =
					"UPDATE "
						+ " "
						+ userTransaction.getDatabase().getSchemaContext().getTableName(SchemaContext.SCHEMA_ACTIVITY_DISPATCH)
						+ " "
						+ "SET    int_dispatch_count=?,int_join_monitor=?,int_dispatch_eventType=?   "
						+ " "
						+ "WHERE  vc_packageid=? "
						+ " "
						+ "AND    vc_processid=? "
						+ " "
						+ "AND    vc_caseid=?  "
						+ " "
						+ "AND    vc_owner_processid=? "
						+ " "
						+ "AND    vc_activityid=? ";
				pstmt = conn.prepareStatement(strSQL);
				pstmt.setInt(1, join_activity_dispatch_count);
				pstmt.setInt(2, join_activity_monitor_count + 1);
				pstmt.setInt(3, ActivityEvent.ACTIVITY_REAL_DISPATCHED);
				pstmt.setString(4, packageId);
				pstmt.setString(5, processId);
				pstmt.setString(6, caseId);
				pstmt.setString(7, join_owner_process_id);
				pstmt.setString(8, join_activity_id);
				JDBCUtilities.cleanupNoThrow(pstmt);
				pstmt = null;
			}

			if (eventResult.isFirst())
			{
				//   -----------------------------------------------------------------
				//		试着找出工作项处理者
				//	 =======================================================
				//	 -----------------------------------------------------------------

				List users =
					WorkflowParticipantSelector.select(
						workflowsession,
						workflowtemplate,
						workflowProcess,
						work,
						workflowTransition,
						userObject);

				if (users != null && users.size() > 1)
				{
					//--------------------------------------------------------------------
					//简化引擎设计,所有汇聚活动节点的参与者必须唯一确定 或者 没有参与者
					//--------------------------------------------------------------------
					throw new WorkflowException("Join Activity Only Can Have One Participant");
				}

				WorkflowParticipant performer = null;
				if (users != null && users.size() == 1)
				{
					performer = (WorkflowParticipant) users.get(0);
				}
				join_work_uuid =
					caseDatabase.createWork(
						workflowsession,
						userTransaction,
						workflowProcess,
						work.getCase(),
						joinActivity,
						null,
						performer,
						work.getDispatchTime(),
						WorkEvent.SUBMITED,
						WorkflowWork.DEFAULT_PRIORITY);

			}

			eventResult.setJoinWorkUUID(join_work_uuid);
		}
		catch (Exception ex)
		{
			ex.printStackTrace();
			eventResult.setJoinException(ex);
		}
		finally
		{
			JDBCUtilities.cleanupNoThrow(pstmt);
		}

		return eventResult;
	}

	protected static JoinEventGuard submit_xorJoin(
		WorkflowSession workflowsession,
		WorkflowXPDL workflowtemplate,
		WorkflowTransaction eventTransaction,
		WorkflowTransaction userTransaction,
		WorkflowProcess workflowProcess,
		WorkflowWork work,
		WorkflowTransition workflowTransition,
		Map userObject)
	{
		WorkflowCaseDatabase caseDatabase = workflowtemplate.getWorkflowTemplate().getCaseDatabase();

		WorkflowCase workflowCase = work.getCase();

		WorkflowActivity srcActivity = workflowTransition.getFromActivity();
		String src_owner_process_id = srcActivity.getWorkflowProcess().getUUID();
		String src_activity_id = srcActivity.getUUID();

		WorkflowActivity joinActivity = workflowTransition.getToActivity();
		String join_owner_process_id = joinActivity.getWorkflowProcess().getUUID();
		String join_activity_id = joinActivity.getUUID();

		String packageId = workflowProcess.getWorkflowPackage().getUUID();
		String processId = workflowProcess.getUUID();
		String caseId = work.getCase().getUUID();

		Connection conn = userTransaction.getConnection();
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		String strSQL = null;

		JoinEventGuard eventResult = new JoinEventGuard(work);

		try
		{
			//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

			int src_activity_dispatch_count = 0;

			//--------------------------------------------------------------------
			// DISP ACTIVITY DISPATCH INFO
			// 1. 取得本次分发的工作项所归属的活动节点信息
			//--------------------------------------------------------------------
			strSQL =
				"SELECT  int_dispatch_count  FROM "
					+ " "
					+ userTransaction.getDatabase().getSchemaContext().getTableName(SchemaContext.SCHEMA_ACTIVITY_DISPATCH)
					+ " "
					+ "WHERE  vc_packageid=? "
					+ " "
					+ "AND    vc_processid=? "
					+ " "
					+ "AND    vc_caseid=?  "
					+ " "
					+ "AND    vc_owner_processid=? "
					+ " "
					+ "AND    vc_activityid=? ";

			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, packageId);
			pstmt.setString(2, processId);
			pstmt.setString(3, caseId);
			pstmt.setString(4, src_owner_process_id);
			pstmt.setString(5, src_activity_id);

			rs = pstmt.executeQuery();
			if (rs.next())
			{
				src_activity_dispatch_count = rs.getInt("int_dispatch_count");
				eventResult.setDispatchCount(src_activity_dispatch_count);
			}

			//--------------------------------------------------------------------
			// JOIN ACTIVITY DISPATCH INFO
			// 2.取得工作项即将汇聚的活动节点信息
			//--------------------------------------------------------------------
			int join_activity_dispatch_count = 0;

			rs.close();

			pstmt.setString(1, packageId);
			pstmt.setString(2, processId);
			pstmt.setString(3, caseId);
			pstmt.setString(4, join_owner_process_id);
			pstmt.setString(5, join_activity_id);

			rs = pstmt.executeQuery();
			if (rs.next())
			{
				join_activity_dispatch_count = rs.getInt("int_dispatch_count");
			}

			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;

			if ((src_activity_dispatch_count + 1) <= join_activity_dispatch_count)
			{
				eventResult.setFirst(false);
				eventResult.setLast(false);

				return eventResult;
			}

			//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++	
			// 3. 取得汇聚的活动节点当前完成的前继工作项信息
			//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++	

			if (src_activity_dispatch_count == join_activity_dispatch_count)
			{
				eventResult.setFirst(true);
				eventResult.setLast(true);
			}
			else
			{
				eventResult.setFirst(false);
				eventResult.setLast(false);

				return eventResult;
			}

			if (join_activity_dispatch_count == 0)
			{
				strSQL =
					"INSERT INTO  "
						+ userTransaction.getDatabase().getSchemaContext().getTableName(SchemaContext.SCHEMA_ACTIVITY_DISPATCH)
						+ "(vc_packageid,vc_processid,vc_caseid,vc_owner_processid,vc_activityid,int_dispatch_count) "
						+ " VALUES(?,?,?,?,?,?)";
				pstmt = conn.prepareStatement(strSQL);
				pstmt.setString(1, packageId);
				pstmt.setString(2, processId);
				pstmt.setString(3, caseId);
				pstmt.setString(4, join_owner_process_id);
				pstmt.setString(5, join_activity_id);
				pstmt.setInt(6, join_activity_dispatch_count + 1);
				pstmt.execute();

				JDBCUtilities.cleanupNoThrow(pstmt);
				pstmt = null;
			}
			else
			{
				if (eventResult.isFirst())
				{
					strSQL =
						"UPDATE "
							+ " "
							+ userTransaction.getDatabase().getSchemaContext().getTableName(SchemaContext.SCHEMA_ACTIVITY_DISPATCH)
							+ " "
							+ "SET    int_dispatch_count=?,int_dispatch_eventType=?   "
							+ " "
							+ "WHERE  vc_packageid=? "
							+ " "
							+ "AND    vc_processid=? "
							+ " "
							+ "AND    vc_caseid=?  "
							+ " "
							+ "AND    vc_owner_processid=? "
							+ " "
							+ "AND    vc_activityid=? ";
					pstmt = conn.prepareStatement(strSQL);
					pstmt.setInt(1, join_activity_dispatch_count + 1);
					pstmt.setInt(2, ActivityEvent.ACTIVITY_REAL_DISPATCHED);
					pstmt.setString(3, packageId);
					pstmt.setString(4, processId);
					pstmt.setString(5, caseId);
					pstmt.setString(6, join_owner_process_id);
					pstmt.setString(7, join_activity_id);
					JDBCUtilities.cleanupNoThrow(pstmt);
					pstmt = null;
				}
			}

			if (eventResult.isFirst())
			{
				String join_work_uuid = null;

				//   -----------------------------------------------------------------
				//		试着找出工作项处理者
				//	 =======================================================
				//	 -----------------------------------------------------------------

				List users =
					WorkflowParticipantSelector.select(
						workflowsession,
						workflowtemplate,
						workflowProcess,
						work,
						workflowTransition,
						userObject);

				if (users != null && users.size() > 1)
				{
					//--------------------------------------------------------------------
					//简化引擎设计,所有汇聚活动节点的参与者必须唯一确定 或者 没有参与者
					//--------------------------------------------------------------------
					throw new WorkflowException("Join Activity Only Can Have One Participant");
				}

				WorkflowParticipant performer = null;
				if (users != null && users.size() == 1)
				{
					performer = (WorkflowParticipant) users.get(0);
				}

				join_work_uuid =
					caseDatabase.createWork(
						workflowsession,
						userTransaction,
						workflowProcess,
						work.getCase(),
						joinActivity,
						null,
						performer,
						work.getDispatchTime(),
						WorkEvent.SUBMITED,
						WorkflowWork.DEFAULT_PRIORITY);

				eventResult.setJoinWorkUUID(join_work_uuid);
			}
		}
		catch (Exception ex)
		{
			eventResult.setJoinException(ex);
		}
		finally
		{
			JDBCUtilities.cleanupNoThrow(pstmt);
		}

		return eventResult;
	}

	protected static JoinEventGuard submit_orJoin(
		WorkflowSession workflowsession,
		WorkflowXPDL workflowtemplate,
		WorkflowTransaction eventTransaction,
		WorkflowTransaction userTransaction,
		WorkflowProcess workflowProcess,
		WorkflowWork work,
		WorkflowTransition workflowTransition,
		Map userObject)
	{
		WorkflowCaseDatabase caseDatabase = workflowtemplate.getWorkflowTemplate().getCaseDatabase();

		WorkflowCase workflowCase = work.getCase();

		WorkflowActivity srcActivity = workflowTransition.getFromActivity();
		String src_owner_process_id = srcActivity.getWorkflowProcess().getUUID();
		String src_activity_id = srcActivity.getUUID();

		WorkflowActivity joinActivity = workflowTransition.getToActivity();
		String join_owner_process_id = joinActivity.getWorkflowProcess().getUUID();
		String join_activity_id = joinActivity.getUUID();

		String packageId = workflowProcess.getWorkflowPackage().getUUID();
		String processId = workflowProcess.getUUID();
		String caseId = work.getCase().getUUID();

		Connection conn = userTransaction.getConnection();
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		String strSQL = null;

		JoinEventGuard eventResult = new JoinEventGuard(work);

		try
		{
			//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

			int src_activity_dispatch_count = 0;

			//--------------------------------------------------------------------
			// DISP ACTIVITY DISPATCH INFO
			// 1. 取得本次分发的工作项所归属的活动节点信息
			strSQL =
				"SELECT  int_dispatch_count,int_join_monitor  FROM "
					+ userTransaction.getDatabase().getSchemaContext().getTableName(SchemaContext.SCHEMA_ACTIVITY_DISPATCH)
					+ "  "
					+ "WHERE  vc_packageid=? "
					+ "AND    vc_processid=? "
					+ "AND    vc_caseid=?  "
					+ "AND    vc_owner_processid=? "
					+ "AND    vc_activityid=? ";

			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, packageId);
			pstmt.setString(2, processId);
			pstmt.setString(3, caseId);
			pstmt.setString(4, src_owner_process_id);
			pstmt.setString(5, src_activity_id);

			rs = pstmt.executeQuery();
			if (rs.next())
			{
				src_activity_dispatch_count = rs.getInt("int_dispatch_count");
				eventResult.setDispatchCount(src_activity_dispatch_count);
			}

			//--------------------------------------------------------------------
			// JOIN ACTIVITY DISPATCH INFO
			// 2.取得工作项即将汇聚的活动节点信息
			//--------------------------------------------------------------------
			int join_activity_monitor_count = 0;
			int join_activity_dispatch_count = 0;

			rs.close();

			pstmt.setString(1, packageId);
			pstmt.setString(2, processId);
			pstmt.setString(3, caseId);
			pstmt.setString(4, join_owner_process_id);
			pstmt.setString(5, join_activity_id);

			rs = pstmt.executeQuery();
			if (rs.next())
			{
				join_activity_dispatch_count = rs.getInt("int_dispatch_count");
				join_activity_monitor_count = rs.getInt("int_join_monitor");
			}

			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;

			if ((src_activity_dispatch_count + 1) < join_activity_dispatch_count)
			{
				eventResult.setFirst(false);
				eventResult.setLast(false);

				return eventResult;
			}

			//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++	
			// 3. 取得汇聚的活动节点当前完成的前继工作项信息
			//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
			List inTrans = joinActivity.getValidIncomingTransitions();
			int inTrans_size = inTrans.size();

			int falseTrans_size = 0;
			strSQL =
				"SELECT  int_dispatch_count  FROM "
					+ " "
					+ userTransaction.getDatabase().getSchemaContext().getTableName(SchemaContext.SCHEMA_ACTIVITY_DISPATCH)
					+ " "
					+ "WHERE  int_dispatch_eventType=? "
					+ " "
					+ "AND    vc_packageid=? "
					+ " "
					+ "AND    vc_processid=? "
					+ " "
					+ "AND    vc_caseid=?  "
					+ " "
					+ "AND    vc_owner_processid=? "
					+ " "
					+ "AND    vc_activityid=? ";
			pstmt = conn.prepareStatement(strSQL);

			//userTransaction 没有查找到相应分发信息
			//数据库事务处理的特殊性,引擎将会在另外一个事务进行查询
			//【设计要求主要是针对自动流进行】
			List not_found_inTrans = new ArrayList();

			for (int i = 0; i < inTrans_size; ++i)
			{
				WorkflowTransition flaseTransition = (WorkflowTransition) inTrans.get(i);
				WorkflowActivity falseActivity = flaseTransition.getFromActivity();
				String false_owner_process_id = falseActivity.getWorkflowProcess().getUUID();
				String false_activity_id = falseActivity.getUUID();

				pstmt.setInt(1, ActivityEvent.ACTIVITY_IMAGINARY_DISPATCHED);
				pstmt.setString(2, packageId);
				pstmt.setString(3, processId);
				pstmt.setString(4, caseId);
				pstmt.setString(5, false_owner_process_id);
				pstmt.setString(6, false_activity_id);

				rs = pstmt.executeQuery();
				if (rs.next())
				{
					falseTrans_size += 1;
				}
				else
				{
					not_found_inTrans.add(flaseTransition);
				}
			}
			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;

			//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
			// -----------------Lookup In eventTransaction	---------------------------------
			//------------------VIP Code Section By zosatapo----------------------------------------
			//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$	
			Connection event_conn = null;
			PreparedStatement event_pstmt = null;
			ResultSet event_rs = null;
			try
			{
				event_conn = (Connection) eventTransaction.getConnection();

				strSQL =
					"SELECT  int_dispatch_count  FROM "
						+ " "
						+ userTransaction.getDatabase().getSchemaContext().getTableName(SchemaContext.SCHEMA_ACTIVITY_DISPATCH)
						+ " "
						+ "WHERE  int_dispatch_eventType=? "
						+ " "
						+ "AND    vc_packageid=? "
						+ " "
						+ "AND    vc_processid=? "
						+ " "
						+ "AND    vc_caseid=?  "
						+ " "
						+ "AND    vc_owner_processid=? "
						+ " "
						+ "AND    vc_activityid=? ";
				event_pstmt = event_conn.prepareStatement(strSQL);

				int not_found_inTrans_size = not_found_inTrans.size();
				for (int i = 0; i < not_found_inTrans_size; ++i)
				{
					WorkflowTransition flaseTransition = (WorkflowTransition) not_found_inTrans.get(i);
					WorkflowActivity falseActivity = flaseTransition.getFromActivity();
					String false_owner_process_id = falseActivity.getWorkflowProcess().getUUID();
					String false_activity_id = falseActivity.getUUID();

					event_pstmt.setInt(1, ActivityEvent.ACTIVITY_IMAGINARY_DISPATCHED);
					event_pstmt.setString(2, packageId);
					event_pstmt.setString(3, processId);
					event_pstmt.setString(4, caseId);
					event_pstmt.setString(5, false_owner_process_id);
					event_pstmt.setString(6, false_activity_id);
					event_rs = event_pstmt.executeQuery();
					if (event_rs.next())
					{
						falseTrans_size += 1;
					}

				} //~end for (int i = 0; i < not_found_inTrans_size; ++i)
				JDBCUtilities.cleanupNoThrow(event_pstmt);
				event_pstmt = null;
			}
			finally
			{
				JDBCUtilities.cleanupNoThrow(event_pstmt);
				event_pstmt = null;
			}
			//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$	

			int join_activity_monitor_total = inTrans_size - falseTrans_size;
			//*********************************************************************
			if (src_activity_dispatch_count == join_activity_dispatch_count)
			{
				eventResult.setFirst(true);
				eventResult.setLast(false);
				join_activity_monitor_count = 0;
			}
			else
			{
				eventResult.setFirst(false);
				eventResult.setLast(false);
			}

			//if((join_activity_monitor_count+1) == join_activity_monitor_total)
			if ((join_activity_monitor_count + 1) >= join_activity_monitor_total)
			{
				eventResult.setLast(true);
			}

			if (join_activity_dispatch_count == 0)
			{
				strSQL =
					"INSERT INTO  "
						+ userTransaction.getDatabase().getSchemaContext().getTableName(SchemaContext.SCHEMA_ACTIVITY_DISPATCH)
						+ "(vc_packageid,vc_processid,vc_caseid,vc_owner_processid,vc_activityid,int_dispatch_count,int_join_monitor) "
						+ " VALUES(?,?,?,?,?,?,?)";
				pstmt = conn.prepareStatement(strSQL);
				pstmt.setString(1, packageId);
				pstmt.setString(2, processId);
				pstmt.setString(3, caseId);
				pstmt.setString(4, join_owner_process_id);
				pstmt.setString(5, join_activity_id);
				pstmt.setInt(6, join_activity_dispatch_count + 1);
				pstmt.setInt(7, join_activity_monitor_count + 1);
				pstmt.execute();

				JDBCUtilities.cleanupNoThrow(pstmt);
				pstmt = null;
			}
			else
			{
				if (eventResult.isFirst())
				{
					join_activity_dispatch_count += 1; //增加
				}
				strSQL =
					"UPDATE "
						+ " "
						+ userTransaction.getDatabase().getSchemaContext().getTableName(SchemaContext.SCHEMA_ACTIVITY_DISPATCH)
						+ " "
						+ "SET    int_dispatch_count=?,int_join_monitor=?,int_dispatch_eventType=?   "
						+ " "
						+ "WHERE  vc_packageid=? "
						+ " "
						+ "AND    vc_processid=? "
						+ " "
						+ "AND    vc_caseid=?  "
						+ " "
						+ "AND    vc_owner_processid=? "
						+ " "
						+ "AND    vc_activityid=? ";
				pstmt = conn.prepareStatement(strSQL);
				pstmt.setInt(1, join_activity_dispatch_count);
				pstmt.setInt(2, join_activity_monitor_count + 1);
				pstmt.setInt(3, ActivityEvent.ACTIVITY_REAL_DISPATCHED);
				pstmt.setString(4, packageId);
				pstmt.setString(5, processId);
				pstmt.setString(6, caseId);
				pstmt.setString(7, join_owner_process_id);
				pstmt.setString(8, join_activity_id);
				JDBCUtilities.cleanupNoThrow(pstmt);
				pstmt = null;
			}

			String join_work_uuid = null;
			if (eventResult.isFirst())
			{
				//   -----------------------------------------------------------------
				//		试着找出工作项处理者
				//	 =======================================================
				//	 -----------------------------------------------------------------

				List users =
					WorkflowParticipantSelector.select(
						workflowsession,
						workflowtemplate,
						workflowProcess,
						work,
						workflowTransition,
						userObject);

				if (users != null && users.size() > 1)
				{
					//--------------------------------------------------------------------
					//简化引擎设计,所有汇聚活动节点的参与者必须唯一确定 或者 没有参与者
					//--------------------------------------------------------------------
					throw new WorkflowException("Join Activity Only Can Have One Participant");
				}

				WorkflowParticipant performer = null;
				if (users != null && users.size() == 1)
				{
					performer = (WorkflowParticipant) users.get(0);
				}
				join_work_uuid =
					caseDatabase.createWork(
						workflowsession,
						userTransaction,
						workflowProcess,
						work.getCase(),
						joinActivity,
						null,
						performer,
						work.getDispatchTime(),
						WorkEvent.SUBMITED,
						WorkflowWork.DEFAULT_PRIORITY);

			}
			else
			{
				strSQL =
					"SELECT vc_uuid  FROM "
						+ " "
						+ caseDatabase.getSchemaContext().getTableName(SchemaContext.SCHEMA_WORK)
						+ " "
						+ "WHERE  dat_acceptTime IS NULL "
						+ " "
						+ "AND    vc_packageid=? "
						+ " "
						+ "AND    vc_processid=? "
						+ " "
						+ "AND    vc_caseid=?  "
						+ " "
						+ "AND    vc_owner_processid=? "
						+ " "
						+ "AND    vc_activityid=? ";

				pstmt = conn.prepareStatement(strSQL);
				pstmt.setString(1, packageId);
				pstmt.setString(2, processId);
				pstmt.setString(3, caseId);
				pstmt.setString(4, join_owner_process_id);
				pstmt.setString(5, join_activity_id);

				rs = pstmt.executeQuery();

				if (rs.next())
				{
					join_work_uuid = rs.getString("vc_uuid");
				}
				JDBCUtilities.cleanupNoThrow(pstmt);
				pstmt = null;
			}

			eventResult.setJoinWorkUUID(join_work_uuid);
		}
		catch (Exception ex)
		{
			eventResult.setJoinException(ex);
		}
		finally
		{
			JDBCUtilities.cleanupNoThrow(pstmt);
		}

		return eventResult;
	}

	protected static JoinEventGuard submit_instanceAndJoin(
		WorkflowSession workflowsession,
		WorkflowXPDL workflowtemplate,
		WorkflowTransaction eventTransaction,
		WorkflowTransaction userTransaction,
		WorkflowProcess workflowProcess,
		WorkflowWork work,
		WorkflowTransition workflowTransition,
		Map userObject)
	{
		WorkflowCaseDatabase caseDatabase = workflowtemplate.getWorkflowTemplate().getCaseDatabase();
		WorkflowCase workflowCase = work.getCase();
		WorkflowActivity srcActivity = workflowTransition.getFromActivity();
		String src_owner_process_id = srcActivity.getWorkflowProcess().getUUID();
		String src_activity_id = srcActivity.getUUID();

		String packageId = workflowProcess.getWorkflowPackage().getUUID();
		String processId = workflowProcess.getUUID();
		String caseId = workflowCase.getUUID();

		WorkflowActivity joinActivity = workflowTransition.getToActivity();
		String join_owner_process_id = joinActivity.getWorkflowProcess().getUUID();
		String join_activity_id = joinActivity.getUUID();

		Connection conn = userTransaction.getConnection();
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		String strSQL = null;

		JoinEventGuard eventResult = new JoinEventGuard(work);

		try
		{
			String join_work_uuid = null;

			strSQL =
				"SELECT vc_uuid  FROM "
					+ " "
					+ caseDatabase.getSchemaContext().getTableName(SchemaContext.SCHEMA_WORK)
					+ " "
					+ "WHERE  dat_acceptTime IS NULL "
					+ " "
					+ "AND    vc_packageid=? "
					+ " "
					+ "AND    vc_processid=? "
					+ " "
					+ "AND    vc_caseid=?  "
					+ " "
					+ "AND    vc_owner_processid=? "
					+ " "
					+ "AND    vc_activityid=? ";

			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, packageId);
			pstmt.setString(2, processId);
			pstmt.setString(3, caseId);
			pstmt.setString(4, join_owner_process_id);
			pstmt.setString(5, join_activity_id);

			rs = pstmt.executeQuery();
			if (rs.next())
			{
				eventResult.setFirst(false);
				eventResult.setLast(false);
				join_work_uuid = rs.getString("vc_uuid");
			}
			else
			{
				eventResult.setFirst(true);
				eventResult.setLast(false);
			}
			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;

			int join_activity_monitor_count = 0;
			int join_activity_monitor_total = 0;

			strSQL =
				"SELECT vc_batchNo FROM "
					+ " "
					+ caseDatabase.getSchemaContext().getTableName(SchemaContext.SCHEMA_PATH)
					+ " "
					+ "WHERE  vc_packageid=? "
					+ " "
					+ "AND    vc_processid=? "
					+ " "
					+ "AND    vc_caseid=?  "
					+ " "
					+ "AND    vc_to=? ";
			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, packageId);
			pstmt.setString(2, processId);
			pstmt.setString(3, caseId);
			pstmt.setString(4, work.getUUID());
			rs = pstmt.executeQuery();

			rs.next();
			String dispBatchNo = rs.getString("vc_batchNo");

			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;

			strSQL =
				"SELECT count(*) FROM "
					+ " "
					+ caseDatabase.getSchemaContext().getTableName(SchemaContext.SCHEMA_PATH)
					+ " "
					+ "WHERE  vc_packageid=? "
					+ " "
					+ "AND    vc_processid=? "
					+ " "
					+ "AND    vc_caseid=?  "
					+ " "
					+ "AND    vc_batchNo=? ";
			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, packageId);
			pstmt.setString(2, processId);
			pstmt.setString(3, caseId);
			pstmt.setString(4, dispBatchNo);
			rs = pstmt.executeQuery();

			if (rs.next())
			{
				join_activity_monitor_total = rs.getInt(1);
			}

			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;

			if (eventResult.isFirst())
			{
				join_activity_monitor_count = 0;
			}
			else
			{
				//destination  instanceAndJoin activity all in-transitions
				//ONLY ==ONE== in-transition
				List inTrans = joinActivity.getValidIncomingTransitions();
				WorkflowTransition tempTrans = (WorkflowTransition) inTrans.get(0);

				strSQL =
					"SELECT count(*)  FROM "
						+ " "
						+ caseDatabase.getSchemaContext().getTableName(SchemaContext.SCHEMA_PATH)
						+ " "
						+ "WHERE  vc_packageid=? "
						+ " "
						+ "AND    vc_processid=? "
						+ " "
						+ "AND    vc_caseid=?  "
						+ " "
						+ "AND    vc_owner_processid=?  "
						+ " "
						+ "AND    vc_transitionid=? "
						+ " "
						+ "AND    vc_to=? ";
				pstmt = conn.prepareStatement(strSQL);
				pstmt.setString(1, packageId);
				pstmt.setString(2, processId);
				pstmt.setString(3, caseId);
				pstmt.setString(4, tempTrans.getWorkflowProcess().getUUID());
				pstmt.setString(5, tempTrans.getUUID());
				pstmt.setString(6, join_work_uuid);
				rs = pstmt.executeQuery();
				join_activity_monitor_count = rs.getInt(1);
			}

			if ((join_activity_monitor_count + 1) >= join_activity_monitor_total)
			{
				eventResult.setLast(true);
			}

			if (eventResult.isFirst())
			{
				//   -----------------------------------------------------------------
				//		试着找出工作项处理者
				//	 =======================================================
				//	 -----------------------------------------------------------------

				List users =
					WorkflowParticipantSelector.select(
						workflowsession,
						workflowtemplate,
						workflowProcess,
						work,
						workflowTransition,
						userObject);
				if (users != null && users.size() > 1)
				{
					//--------------------------------------------------------------------
					//简化引擎设计,所有汇聚活动节点的参与者必须唯一确定 或者 没有参与者
					//--------------------------------------------------------------------
					throw new WorkflowException("Join Activity Only Can Have One Participant");
				}

				WorkflowParticipant performer = null;
				if (users != null && users.size() == 1)
				{
					performer = (WorkflowParticipant) users.get(0);
				}
				join_work_uuid =
					caseDatabase.createWork(
						workflowsession,
						userTransaction,
						workflowProcess,
						work.getCase(),
						joinActivity,
						null,
						performer,
						work.getDispatchTime(),
						WorkEvent.SUBMITED,
						WorkflowWork.DEFAULT_PRIORITY);

			}

			eventResult.setJoinWorkUUID(join_work_uuid);
		}
		catch (Exception ex)
		{
			eventResult.setJoinException(ex);
		}
		finally
		{
			JDBCUtilities.cleanupNoThrow(pstmt);
		}

		return eventResult;
	}

	protected static JoinEventGuard submit_instanceXorJoin(
		WorkflowSession workflowsession,
		WorkflowXPDL workflowtemplate,
		WorkflowTransaction eventTransaction,
		WorkflowTransaction userTransaction,
		WorkflowProcess workflowProcess,
		WorkflowWork work,
		WorkflowTransition workflowTransition,
		Map userObject)
	{
		WorkflowCaseDatabase caseDatabase = workflowtemplate.getWorkflowTemplate().getCaseDatabase();

		WorkflowCase workflowCase = work.getCase();
		WorkflowActivity srcActivity = workflowTransition.getFromActivity();
		String src_owner_process_id = srcActivity.getWorkflowProcess().getUUID();
		String src_activity_id = srcActivity.getUUID();

		String packageId = workflowProcess.getWorkflowPackage().getUUID();
		String processId = workflowProcess.getUUID();
		String caseId = workflowCase.getUUID();

		WorkflowActivity joinActivity = workflowTransition.getToActivity();
		String join_owner_process_id = joinActivity.getWorkflowProcess().getUUID();
		String join_activity_id = joinActivity.getUUID();

		Connection conn = userTransaction.getConnection();
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		String strSQL = null;

		JoinEventGuard eventResult = new JoinEventGuard(work);

		try
		{

			strSQL =
				"SELECT vc_batchNo FROM "
					+ " "
					+ caseDatabase.getSchemaContext().getTableName(SchemaContext.SCHEMA_PATH)
					+ " "
					+ "WHERE  vc_packageid=? "
					+ " "
					+ "AND    vc_processid=? "
					+ " "
					+ "AND    vc_caseid=?  "
					+ " "
					+ "AND    vc_to=? ";
			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, packageId);
			pstmt.setString(2, processId);
			pstmt.setString(3, caseId);
			pstmt.setString(4, work.getUUID());
			rs = pstmt.executeQuery();

			String dispBatchNo = null;
			if (rs.next())
			{
				dispBatchNo = rs.getString("vc_batchNo");
			}

			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;

			int join_activity_monitor_count = 0;
			int join_activity_monitor_total = 0;

			strSQL =
				"SELECT vc_to FROM "
					+ " "
					+ caseDatabase.getSchemaContext().getTableName(SchemaContext.SCHEMA_PATH)
					+ " "
					+ "WHERE  vc_packageid=? "
					+ " "
					+ "AND    vc_processid=? "
					+ " "
					+ "AND    vc_caseid=?  "
					+ " "
					+ "AND    vc_batchNo=? ";
			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, packageId);
			pstmt.setString(2, processId);
			pstmt.setString(3, caseId);
			pstmt.setString(4, dispBatchNo);
			rs = pstmt.executeQuery();

			Vector vector_work_id = new Vector();
			while (rs.next())
			{
				vector_work_id.addElement(rs.getString("vc_to"));
			}
			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;

			strSQL =
				"SELECT vc_to FROM "
					+ " "
					+ caseDatabase.getSchemaContext().getTableName(SchemaContext.SCHEMA_PATH)
					+ " "
					+ "WHERE  vc_packageid=? "
					+ " "
					+ "AND    vc_processid=? "
					+ " "
					+ "AND    vc_caseid=?  "
					+ "AND    vc_from=? ";
			pstmt = conn.prepareStatement(strSQL);
			int src_work_total = vector_work_id.size();

			eventResult.setFirst(true);
			eventResult.setLast(true);

			for (int i = 0; i < src_work_total; ++i)
			{

				pstmt.setString(1, packageId);
				pstmt.setString(2, processId);
				pstmt.setString(3, caseId);
				pstmt.setString(4, (String) vector_work_id.elementAt(i));
				rs = pstmt.executeQuery();

				if (rs.next())
				{
					eventResult.setFirst(false);
					eventResult.setLast(false);
					break;
				}

			}

			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;

			String join_work_uuid = null;

			if (eventResult.isFirst())
			{
				//   -----------------------------------------------------------------
				//		试着找出工作项处理者
				//	 =======================================================
				//	 -----------------------------------------------------------------
				List users =
					WorkflowParticipantSelector.select(
						workflowsession,
						workflowtemplate,
						workflowProcess,
						work,
						workflowTransition,
						userObject);
				if (users != null && users.size() > 1)
				{
					//--------------------------------------------------------------------
					//简化引擎设计,所有汇聚活动节点的参与者必须唯一确定 或者 没有参与者
					//--------------------------------------------------------------------
					throw new WorkflowException("Join Activity Only Can Have One Participant");
				}

				WorkflowParticipant performer = null;

				if (users != null && users.size() == 1)
				{
					performer = (WorkflowParticipant) users.get(0);
				}
				join_work_uuid =
					caseDatabase.createWork(
						workflowsession,
						userTransaction,
						workflowProcess,
						work.getCase(),
						joinActivity,
						null,
						performer,
						work.getDispatchTime(),
						WorkEvent.SUBMITED,
						WorkflowWork.DEFAULT_PRIORITY);
			}

			eventResult.setJoinWorkUUID(join_work_uuid);
		}
		catch (Exception ex)
		{
			eventResult.setJoinException(ex);
		}
		finally
		{
			JDBCUtilities.cleanupNoThrow(pstmt);
		}

		return eventResult;
	}

	protected static JoinEventGuard submit_weightJoin(
		WorkflowSession workflowsession,
		WorkflowXPDL workflowtemplate,
		WorkflowTransaction eventTransaction,
		WorkflowTransaction userTransaction,
		WorkflowProcess workflowProcess,
		WorkflowWork work,
		WorkflowTransition workflowTransition,
		Map userObject)
	{
		WorkflowCaseDatabase caseDatabase = workflowtemplate.getWorkflowTemplate().getCaseDatabase();

		WorkflowCase workflowCase = work.getCase();

		WorkflowActivity srcActivity = workflowTransition.getFromActivity();
		String src_owner_process_id = srcActivity.getWorkflowProcess().getUUID();
		String src_activity_id = srcActivity.getUUID();

		WorkflowActivity joinActivity = workflowTransition.getToActivity();
		String join_owner_process_id = joinActivity.getWorkflowProcess().getUUID();
		String join_activity_id = joinActivity.getUUID();

		String packageId = workflowProcess.getWorkflowPackage().getUUID();
		String processId = workflowProcess.getUUID();
		String caseId = work.getCase().getUUID();

		Connection conn = userTransaction.getConnection();
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		String strSQL = null;

		JoinEventGuard eventResult = new JoinEventGuard(work);

		try
		{
			//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

			int src_activity_dispatch_count = 0;

			//--------------------------------------------------------------------
			// DISP ACTIVITY DISPATCH INFO
			// 1. 取得本次分发的工作项所归属的活动节点信息
			strSQL =
				"SELECT  int_dispatch_count,int_join_monitor  FROM "
					+ userTransaction.getDatabase().getSchemaContext().getTableName(SchemaContext.SCHEMA_ACTIVITY_DISPATCH)
					+ "  "
					+ "WHERE  vc_packageid=? "
					+ "AND    vc_processid=? "
					+ "AND    vc_caseid=?  "
					+ "AND    vc_owner_processid=? "
					+ "AND    vc_activityid=? ";

			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, packageId);
			pstmt.setString(2, processId);
			pstmt.setString(3, caseId);
			pstmt.setString(4, src_owner_process_id);
			pstmt.setString(5, src_activity_id);

			rs = pstmt.executeQuery();
			if (rs.next())
			{
				src_activity_dispatch_count = rs.getInt("int_dispatch_count");
				eventResult.setDispatchCount(src_activity_dispatch_count);
			}
			rs.close();

			//--------------------------------------------------------------------
			// JOIN ACTIVITY DISPATCH INFO
			// 2.取得工作项即将汇聚的活动节点信息
			//--------------------------------------------------------------------
			int join_activity_monitor_count = 0;
			double join_activity_monitor_weight = 0;
			int join_activity_dispatch_count = 0;

			double join_threshold = 0;

			ExtendedAttribute tempEA = joinActivity.findExtendedAttribute(XPDLGlobals.JOIN_THRESHOLD);
			if (tempEA != null && tempEA.getValue() != null)
			{
				join_threshold = Double.parseDouble(tempEA.getValue());
			}

			pstmt.setString(1, packageId);
			pstmt.setString(2, processId);
			pstmt.setString(3, caseId);
			pstmt.setString(4, join_owner_process_id);
			pstmt.setString(5, join_activity_id);

			rs = pstmt.executeQuery();
			if (rs.next())
			{
				join_activity_dispatch_count = rs.getInt("int_dispatch_count");
				join_activity_monitor_count = rs.getInt("int_join_monitor");
				join_activity_monitor_weight = rs.getDouble("dbl_join_monitor");
			}

			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;

			if ((src_activity_dispatch_count + 1) < join_activity_dispatch_count)
			{
				eventResult.setFirst(false);
				eventResult.setLast(false);

				return eventResult;
			}

			//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++	
			// 3. 取得汇聚的活动节点当前完成的前继工作项信息
			//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
			List inTrans = joinActivity.getValidIncomingTransitions();
			int inTrans_size = inTrans.size();

			int falseTrans_size = 0;
			strSQL =
				"SELECT  int_dispatch_count  FROM "
					+ " "
					+ userTransaction.getDatabase().getSchemaContext().getTableName(SchemaContext.SCHEMA_ACTIVITY_DISPATCH)
					+ " "
					+ "WHERE  int_dispatch_eventType=? "
					+ " "
					+ "AND    vc_packageid=? "
					+ " "
					+ "AND    vc_processid=? "
					+ " "
					+ "AND    vc_caseid=?  "
					+ " "
					+ "AND    vc_owner_processid=? "
					+ " "
					+ "AND    vc_activityid=? ";
			pstmt = conn.prepareStatement(strSQL);

			//userTransaction 没有查找到相应分发信息
			//数据库事务处理的特殊性,引擎将会在另外一个事务进行查询
			//【设计要求主要是针对自动流进行】
			List not_found_inTrans = new ArrayList();

			for (int i = 0; i < inTrans_size; ++i)
			{
				WorkflowTransition flaseTransition = (WorkflowTransition) inTrans.get(i);
				WorkflowActivity falseActivity = flaseTransition.getFromActivity();
				String false_owner_process_id = falseActivity.getWorkflowProcess().getUUID();
				String false_activity_id = falseActivity.getUUID();

				pstmt.setInt(1, ActivityEvent.ACTIVITY_IMAGINARY_DISPATCHED);
				pstmt.setString(2, packageId);
				pstmt.setString(3, processId);
				pstmt.setString(4, caseId);
				pstmt.setString(5, false_owner_process_id);
				pstmt.setString(6, false_activity_id);

				rs = pstmt.executeQuery();
				if (rs.next())
				{
					falseTrans_size += 1;
				}
				else
				{
					not_found_inTrans.add(flaseTransition);
				}
			}
			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;

			//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
			// -----------------Lookup In eventTransaction	---------------------------------
			//------------------VIP Code Section By zosatapo----------------------------------------
			//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$	
			Connection event_conn = null;
			PreparedStatement event_pstmt = null;
			ResultSet event_rs = null;
			try
			{
				event_conn = (Connection) eventTransaction.getConnection();

				strSQL =
					"SELECT  int_dispatch_count  FROM "
						+ " "
						+ userTransaction.getDatabase().getSchemaContext().getTableName(SchemaContext.SCHEMA_ACTIVITY_DISPATCH)
						+ " "
						+ "WHERE  int_dispatch_eventType=? "
						+ " "
						+ "AND    vc_packageid=? "
						+ " "
						+ "AND    vc_processid=? "
						+ " "
						+ "AND    vc_caseid=?  "
						+ " "
						+ "AND    vc_owner_processid=? "
						+ " "
						+ "AND    vc_activityid=? ";
				event_pstmt = event_conn.prepareStatement(strSQL);

				int not_found_inTrans_size = not_found_inTrans.size();
				for (int i = 0; i < not_found_inTrans_size; ++i)
				{
					WorkflowTransition flaseTransition = (WorkflowTransition) not_found_inTrans.get(i);
					WorkflowActivity falseActivity = flaseTransition.getFromActivity();
					String false_owner_process_id = falseActivity.getWorkflowProcess().getUUID();
					String false_activity_id = falseActivity.getUUID();

					event_pstmt.setInt(1, ActivityEvent.ACTIVITY_IMAGINARY_DISPATCHED);
					event_pstmt.setString(2, packageId);
					event_pstmt.setString(3, processId);
					event_pstmt.setString(4, caseId);
					event_pstmt.setString(5, false_owner_process_id);
					event_pstmt.setString(6, false_activity_id);
					event_rs = event_pstmt.executeQuery();
					if (event_rs.next())
					{
						falseTrans_size += 1;
					}

				} //~end for (int i = 0; i < not_found_inTrans_size; ++i)
				JDBCUtilities.cleanupNoThrow(event_pstmt);
				event_pstmt = null;
			}
			finally
			{
				JDBCUtilities.cleanupNoThrow(event_pstmt);
				event_pstmt = null;
			}
			//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$	

			int join_activity_monitor_total = inTrans_size - falseTrans_size;
			//*********************************************************************
			if (src_activity_dispatch_count == join_activity_dispatch_count)
			{
				eventResult.setFirst(true);
				eventResult.setLast(false);
				join_activity_monitor_count = 0;
			}
			else
			{
				eventResult.setFirst(false);
				eventResult.setLast(false);
			}

			//if((join_activity_monitor_count+1) == join_activity_monitor_total)
			if ((join_activity_monitor_count + 1) >= join_activity_monitor_total)
			{
				eventResult.setLast(true);
			}

			if (join_activity_dispatch_count == 0)
			{
				strSQL =
					"INSERT INTO  "
						+ userTransaction.getDatabase().getSchemaContext().getTableName(SchemaContext.SCHEMA_ACTIVITY_DISPATCH)
						+ "(vc_packageid,vc_processid,vc_caseid,vc_owner_processid,vc_activityid,int_dispatch_count,int_join_monitor) "
						+ " VALUES(?,?,?,?,?,?,?)";
				pstmt = conn.prepareStatement(strSQL);
				pstmt.setString(1, packageId);
				pstmt.setString(2, processId);
				pstmt.setString(3, caseId);
				pstmt.setString(4, join_owner_process_id);
				pstmt.setString(5, join_activity_id);
				pstmt.setInt(6, join_activity_dispatch_count + 1);
				pstmt.setInt(7, join_activity_monitor_count + 1);
				pstmt.execute();

				JDBCUtilities.cleanupNoThrow(pstmt);
				pstmt = null;
			}
			else
			{
				if (eventResult.isFirst())
				{
					join_activity_dispatch_count += 1; //增加
				}
				strSQL =
					"UPDATE "
						+ " "
						+ userTransaction.getDatabase().getSchemaContext().getTableName(SchemaContext.SCHEMA_ACTIVITY_DISPATCH)
						+ " "
						+ "SET    int_dispatch_count=?,int_join_monitor=?,int_dispatch_eventType=?   "
						+ " "
						+ "WHERE  vc_packageid=? "
						+ " "
						+ "AND    vc_processid=? "
						+ " "
						+ "AND    vc_caseid=?  "
						+ " "
						+ "AND    vc_owner_processid=? "
						+ " "
						+ "AND    vc_activityid=? ";
				pstmt = conn.prepareStatement(strSQL);
				pstmt.setInt(1, join_activity_dispatch_count);
				pstmt.setInt(2, join_activity_monitor_count + 1);
				pstmt.setInt(3, ActivityEvent.ACTIVITY_REAL_DISPATCHED);
				pstmt.setString(4, packageId);
				pstmt.setString(5, processId);
				pstmt.setString(6, caseId);
				pstmt.setString(7, join_owner_process_id);
				pstmt.setString(8, join_activity_id);
				JDBCUtilities.cleanupNoThrow(pstmt);
				pstmt = null;
			}

			String join_work_uuid = null;
			if (eventResult.isFirst())
			{
				//   -----------------------------------------------------------------
				//		试着找出工作项处理者
				//	 =======================================================
				//	 -----------------------------------------------------------------
				List users =
					WorkflowParticipantSelector.select(
						workflowsession,
						workflowtemplate,
						workflowProcess,
						work,
						workflowTransition,
						userObject);

				if (users != null && users.size() > 1)
				{
					//--------------------------------------------------------------------
					//简化引擎设计,所有汇聚活动节点的参与者必须唯一确定 或者 没有参与者
					//--------------------------------------------------------------------
					throw new WorkflowException("Join Activity Only Can Have One Participant");
				}

				WorkflowParticipant performer = null;

				if (users != null && users.size() == 1)
				{
					performer = (WorkflowParticipant) users.get(0);
				}
				join_work_uuid =
					caseDatabase.createWork(
						workflowsession,
						userTransaction,
						workflowProcess,
						work.getCase(),
						joinActivity,
						null,
						performer,
						work.getDispatchTime(),
						WorkEvent.SUBMITED,
						WorkflowWork.DEFAULT_PRIORITY);

			}
			else
			{
				strSQL =
					"SELECT vc_uuid  FROM "
						+ " "
						+ caseDatabase.getSchemaContext().getTableName(SchemaContext.SCHEMA_WORK)
						+ " "
						+ "WHERE  dat_acceptTime IS NULL "
						+ " "
						+ "AND    vc_packageid=? "
						+ " "
						+ "AND    vc_processid=? "
						+ " "
						+ "AND    vc_caseid=?  "
						+ " "
						+ "AND    vc_owner_processid=? "
						+ " "
						+ "AND    vc_activityid=? ";

				pstmt = conn.prepareStatement(strSQL);
				pstmt.setString(1, packageId);
				pstmt.setString(2, processId);
				pstmt.setString(3, caseId);
				pstmt.setString(4, join_owner_process_id);
				pstmt.setString(5, join_activity_id);

				rs = pstmt.executeQuery();

				if (rs.next())
				{
					join_work_uuid = rs.getString("vc_uuid");
				}
				JDBCUtilities.cleanupNoThrow(pstmt);
				pstmt = null;
			}

			eventResult.setJoinWorkUUID(join_work_uuid);
		}
		catch (Exception ex)
		{
			eventResult.setJoinException(ex);
		}
		finally
		{
			JDBCUtilities.cleanupNoThrow(pstmt);
		}

		return eventResult;
	}

	protected static JoinEventGuard submit_instanceWeightJoin(
		WorkflowSession workflowsession,
		WorkflowXPDL workflowtemplate,
		WorkflowTransaction eventTransaction,
		WorkflowTransaction userTransaction,
		WorkflowProcess workflowProcess,
		WorkflowWork work,
		WorkflowTransition workflowTransition,
		Map userObject)
	{
		WorkflowCaseDatabase caseDatabase = workflowtemplate.getWorkflowTemplate().getCaseDatabase();

		WorkflowCase workflowCase = work.getCase();
		WorkflowActivity srcActivity = workflowTransition.getFromActivity();
		String src_owner_process_id = srcActivity.getWorkflowProcess().getUUID();
		String src_activity_id = srcActivity.getUUID();

		String packageId = workflowProcess.getWorkflowPackage().getUUID();
		String processId = workflowProcess.getUUID();
		String caseId = workflowCase.getUUID();

		WorkflowActivity joinActivity = workflowTransition.getToActivity();
		String join_owner_process_id = joinActivity.getWorkflowProcess().getUUID();
		String join_activity_id = joinActivity.getUUID();

		Connection conn = (Connection) userTransaction.getConnection();
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		String strSQL = null;

		JoinEventGuard eventResult = new JoinEventGuard(work);

		try
		{
			String join_work_uuid = null;

			strSQL =
				"SELECT vc_uuid  FROM "
					+ " "
					+ caseDatabase.getSchemaContext().getTableName(SchemaContext.SCHEMA_WORK)
					+ " "
					+ "WHERE  dat_acceptTime IS NULL "
					+ " "
					+ "AND    vc_packageid=? "
					+ " "
					+ "AND    vc_processid=? "
					+ " "
					+ "AND    vc_caseid=?  "
					+ " "
					+ "AND    vc_owner_processid=? "
					+ " "
					+ "AND    vc_activityid=? ";

			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, packageId);
			pstmt.setString(2, processId);
			pstmt.setString(3, caseId);
			pstmt.setString(4, join_owner_process_id);
			pstmt.setString(5, join_activity_id);

			rs = pstmt.executeQuery();
			if (rs.next())
			{
				eventResult.setFirst(false);
				eventResult.setLast(false);
				join_work_uuid = rs.getString("vc_uuid");
			}
			else
			{
				eventResult.setFirst(true);
				eventResult.setLast(false);
			}
			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;

			int join_activity_monitor_count = 0;
			int join_activity_monitor_total = 0;

			strSQL =
				"SELECT vc_batchNo FROM "
					+ " "
					+ caseDatabase.getSchemaContext().getTableName(SchemaContext.SCHEMA_PATH)
					+ " "
					+ "WHERE  vc_packageid=? "
					+ " "
					+ "AND    vc_processid=? "
					+ " "
					+ "AND    vc_caseid=?  "
					+ " "
					+ "AND    vc_to=? ";
			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, packageId);
			pstmt.setString(2, processId);
			pstmt.setString(3, caseId);
			pstmt.setString(4, work.getUUID());
			rs = pstmt.executeQuery();

			rs.next();
			String dispBatchNo = rs.getString("vc_batchNo");

			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;

			strSQL =
				"SELECT count(*) FROM "
					+ " "
					+ caseDatabase.getSchemaContext().getTableName(SchemaContext.SCHEMA_PATH)
					+ " "
					+ "WHERE  vc_packageid=? "
					+ " "
					+ "AND    vc_processid=? "
					+ " "
					+ "AND    vc_caseid=?  "
					+ " "
					+ "AND    vc_batchNo=? ";
			pstmt = conn.prepareStatement(strSQL);
			pstmt.setString(1, packageId);
			pstmt.setString(2, processId);
			pstmt.setString(3, caseId);
			pstmt.setString(4, dispBatchNo);
			rs = pstmt.executeQuery();

			if (rs.next())
			{
				join_activity_monitor_total = rs.getInt(1);
			}

			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;

			if (eventResult.isFirst())
			{
				join_activity_monitor_count = 0;
			}
			else
			{
				//destination  instanceAndJoin activity all in-transitions
				//ONLY ==ONE== in-transition
				List inTrans = joinActivity.getValidIncomingTransitions();
				WorkflowTransition tempTrans = (WorkflowTransition) inTrans.get(0);

				strSQL =
					"SELECT count(*)  FROM "
						+ " "
						+ caseDatabase.getSchemaContext().getTableName(SchemaContext.SCHEMA_PATH)
						+ " "
						+ "WHERE  vc_packageid=? "
						+ " "
						+ "AND    vc_processid=? "
						+ " "
						+ "AND    vc_caseid=?  "
						+ " "
						+ "AND    vc_owner_processid=?  "
						+ " "
						+ "AND    vc_transitionid=? "
						+ " "
						+ "AND    vc_to=? ";
				pstmt = conn.prepareStatement(strSQL);
				pstmt.setString(1, packageId);
				pstmt.setString(2, processId);
				pstmt.setString(3, caseId);
				pstmt.setString(4, tempTrans.getWorkflowProcess().getUUID());
				pstmt.setString(5, tempTrans.getUUID());
				pstmt.setString(6, join_work_uuid);
				rs = pstmt.executeQuery();
				join_activity_monitor_count = rs.getInt(1);
			}

			if ((join_activity_monitor_count + 1) >= join_activity_monitor_total)
			{
				eventResult.setLast(true);
			}

			if (eventResult.isFirst())
			{
				//   -----------------------------------------------------------------
				//		试着找出工作项处理者
				//	 =======================================================
				//	 -----------------------------------------------------------------

				List users =
					WorkflowParticipantSelector.select(
						workflowsession,
						workflowtemplate,
						workflowProcess,
						work,
						workflowTransition,
						userObject);
				if (users != null && users.size() > 1)
				{
					//--------------------------------------------------------------------
					//简化引擎设计,所有汇聚活动节点的参与者必须唯一确定 或者 没有参与者
					//--------------------------------------------------------------------
					throw new WorkflowException("Join Activity Only Can Have One Participant");
				}

				WorkflowParticipant performer = null;
				if (users != null && users.size() == 1)
				{
					performer = (WorkflowParticipant) users.get(0);
				}
				join_work_uuid =
					caseDatabase.createWork(
						workflowsession,
						userTransaction,
						workflowProcess,
						work.getCase(),
						joinActivity,
						null,
						performer,
						work.getDispatchTime(),
						WorkEvent.SUBMITED,
						WorkflowWork.DEFAULT_PRIORITY);

			}

			eventResult.setJoinWorkUUID(join_work_uuid);
		}
		catch (Exception ex)
		{
			eventResult.setJoinException(ex);
		}
		finally
		{
			JDBCUtilities.cleanupNoThrow(pstmt);
		}

		return eventResult;
	}
}
