//----------------------------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.coreImpl.store;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.huihoo.commons.jdbc.JDBCUtilities;
import org.huihoo.workflow.SchemaContext;
import org.huihoo.workflow.WorkflowException;
import org.huihoo.workflow.WorkflowTransaction;
import org.huihoo.workflow.coreImpl.util.StringManager;
import org.huihoo.workflow.event.ActivityEvent;
import org.huihoo.workflow.event.EventQueue;
import org.huihoo.workflow.event.JoinEvent;
import org.huihoo.workflow.event.JoinEventGuard;
import org.huihoo.workflow.event.WorkEvent;
import org.huihoo.workflow.server.WorkflowCase;
import org.huihoo.workflow.server.WorkflowSession;
import org.huihoo.workflow.server.WorkflowWork;
import org.huihoo.workflow.server.WorkflowXPDL;
import org.huihoo.workflow.store.WorkflowCaseDatabase;
import org.huihoo.workflow.xpdl.WorkflowActivity;
import org.huihoo.workflow.xpdl.WorkflowProcess;
import org.huihoo.workflow.xpdl.WorkflowTransition;
import org.huihoo.workflow.xpdl.activity.JoinType;

public class JoinActivityDispatcher
{
	private static Log log = LogFactory.getLog("willow.JoinActivityDispatcher");
	/**
	 * The string manager for this package.
	 */
	private static StringManager sm = StringManager.getManager(org.huihoo.workflow.coreImpl.store.Constants.PACKAGE);

	public static boolean submit_join(
		WorkflowSession workflowsession,
		WorkflowXPDL workflowtemplate,
		WorkflowTransaction userTransaction,
		WorkflowProcess workflowProcess,
		WorkflowWork work,
		WorkflowTransition workflowTransition,
		String pathSubmitBatch,
		Map userObject)
		throws WorkflowException, InterruptedException
	{
		JoinType joinType = workflowTransition.getToActivity().getJoinType();
		if (JoinType.JOIN_AND.equals(joinType))
		{
			return submit_andJoin(
				workflowsession,
				workflowtemplate,
				userTransaction,
				workflowProcess,
				work,
				workflowTransition,
				pathSubmitBatch,
				userObject);
		}
		else if (JoinType.JOIN_XOR.equals(joinType))
		{
			return submit_xorJoin(
				workflowsession,
				workflowtemplate,
				userTransaction,
				workflowProcess,
				work,
				workflowTransition,
				pathSubmitBatch,
				userObject);
		}
		else if (JoinType.JOIN_OR.equals(joinType))
		{
			return submit_orJoin(
				workflowsession,
				workflowtemplate,
				userTransaction,
				workflowProcess,
				work,
				workflowTransition,
				pathSubmitBatch,
				userObject);
		}
		else if (JoinType.JOIN_WEIGHT.equals(joinType))
		{
			return submit_weightJoin(
				workflowsession,
				workflowtemplate,
				userTransaction,
				workflowProcess,
				work,
				workflowTransition,
				pathSubmitBatch,
				userObject);
		}
		else if (JoinType.JOIN_ROUTE.equals(joinType))
		{
			return submit_routeJoin(
				workflowsession,
				workflowtemplate,
				userTransaction,
				workflowProcess,
				work,
				workflowTransition,
				pathSubmitBatch,
				userObject);
		}
		else if (JoinType.JOIN_INSTANCE_AND.equals(joinType))
		{
			return submit_instanceAndJoin(
				workflowsession,
				workflowtemplate,
				userTransaction,
				workflowProcess,
				work,
				workflowTransition,
				pathSubmitBatch,
				userObject);
		}
		else if (JoinType.JOIN_INSTANCE_XOR.equals(joinType))
		{
			return submit_instanceXorJoin(
				workflowsession,
				workflowtemplate,
				userTransaction,
				workflowProcess,
				work,
				workflowTransition,
				pathSubmitBatch,
				userObject);
		}
		else if (JoinType.JOIN_INSTANCE_WEIGHT.equals(joinType))
		{
			return submit_instanceWeightJoin(
				workflowsession,
				workflowtemplate,
				userTransaction,
				workflowProcess,
				work,
				workflowTransition,
				pathSubmitBatch,
				userObject);
		}
		throw new WorkflowException("JoinType '" + joinType + "' not supported by current realse");
	}

	protected static boolean submit_andJoin(
		WorkflowSession workflowsession,
		WorkflowXPDL workflowtemplate,
		WorkflowTransaction userTransaction,
		WorkflowProcess workflowProcess,
		WorkflowWork work,
		WorkflowTransition workflowTransition,
		String pathSubmitBatch,
		Map userObject)
		throws WorkflowException, InterruptedException
	{
		log.debug("workitem ==> " + work + " || transition ==> " + workflowTransition);
		WorkflowCaseDatabase caseDatabase = workflowtemplate.getWorkflowTemplate().getCaseDatabase();

		EventQueue eventQueue = caseDatabase.getWorkflowTemplate().getOwnerWorkflowXPDL().getEventQueue();
		JoinEvent monitorEvent =
			new JoinEvent(
				work,
				JoinEvent.JOIN_AND,
				workflowsession,
				workflowtemplate,
				userTransaction,
				workflowProcess,
				workflowTransition,
				userObject);
		eventQueue.postEvent(monitorEvent);

		JoinEventGuard eventResult = monitorEvent.getJoinEventGuard();

		if (eventResult.getJoinException() != null)
		{
			throw new WorkflowException(eventResult.getJoinException());
		}

		Connection conn = userTransaction.getConnection();
		PreparedStatement pstmt = null;
		String strSQL = null;
		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();

		log.debug("\nandJoin monitorEvent == > " + monitorEvent);

		try
		{
			if (eventResult.getDispatchCount() == 0)
			{
				strSQL =
					"INSERT INTO  "
						+ caseDatabase.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, src_owner_process_id);
				pstmt.setString(5, src_activity_id);
				pstmt.setInt(6, eventResult.getDispatchCount() + 1);
				pstmt.execute();

				JDBCUtilities.cleanupNoThrow(pstmt);
				pstmt = null;
			}
			else
			{
				strSQL =
					"UPDATE "
						+ caseDatabase.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, eventResult.getDispatchCount() + 1);
				pstmt.setInt(2, ActivityEvent.ACTIVITY_REAL_DISPATCHED);
				pstmt.setString(3, packageId);
				pstmt.setString(4, processId);
				pstmt.setString(5, caseId);
				pstmt.setString(6, src_owner_process_id);
				pstmt.setString(7, src_activity_id);
				JDBCUtilities.cleanupNoThrow(pstmt);
				pstmt = null;
			}
		}
		catch (SQLException e)
		{
			WorkflowException ex = new WorkflowException("can not submit workflow work (AND_JOIN)");
			ex.setRootCause(e);
			throw ex;
		}
		finally
		{
			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;
		}

		String andJoinWorkUUID = eventResult.getJoinWorkUUID();

		WorkflowWork andJoinWork =
			caseDatabase.findWork(workflowsession, userTransaction, workflowProcess, work.getCase(), andJoinWorkUUID);
		caseDatabase.createPath(
			workflowsession,
			userTransaction,
			workflowProcess,
			work.getCase(),
			work,
			andJoinWork,
			pathSubmitBatch,
			WorkEvent.SUBMITED);

		if (eventResult.isLast())
		{
			return ControllerDispatcher.executeDispatchIfNecessary(
				workflowsession,
				workflowtemplate,
				userTransaction,
				workflowProcess,
				andJoinWork,
				userObject);
		}
		return true;
	}

	protected static boolean submit_xorJoin(
		WorkflowSession workflowsession,
		WorkflowXPDL workflowtemplate,
		WorkflowTransaction userTransaction,
		WorkflowProcess workflowProcess,
		WorkflowWork work,
		WorkflowTransition workflowTransition,
		String pathSubmitBatch,
		Map userObject)
		throws WorkflowException, InterruptedException
	{
		log.debug("workitem ==> " + work + " || transition ==> " + workflowTransition);
		WorkflowCaseDatabase caseDatabase = workflowtemplate.getWorkflowTemplate().getCaseDatabase();
		EventQueue eventQueue = caseDatabase.getWorkflowTemplate().getOwnerWorkflowXPDL().getEventQueue();
		JoinEvent monitorEvent =
			new JoinEvent(
				work,
				JoinEvent.JOIN_XOR,
				workflowsession,
				workflowtemplate,
				userTransaction,
				workflowProcess,
				workflowTransition,
				userObject);
		eventQueue.postEvent(monitorEvent);

		JoinEventGuard eventResult = monitorEvent.getJoinEventGuard();

		if (eventResult.getJoinException() != null)
		{
			//eventResult.getException().printStackTrace();
			throw new WorkflowException(eventResult.getJoinException());
		}

		Connection conn = userTransaction.getConnection();
		PreparedStatement pstmt = null;
		String strSQL = null;
		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();

		//log.debug("\nxorJoin monitorEvent == > " + monitorEvent);

		try
		{
			if (eventResult.getDispatchCount() == 0)
			{
				strSQL =
					"INSERT INTO  "
						+ caseDatabase.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, src_owner_process_id);
				pstmt.setString(5, src_activity_id);
				pstmt.setInt(6, eventResult.getDispatchCount() + 1);
				pstmt.execute();

				JDBCUtilities.cleanupNoThrow(pstmt);
				pstmt = null;
			}
			else
			{
				strSQL =
					"UPDATE "
						+ caseDatabase.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, eventResult.getDispatchCount() + 1);
				pstmt.setInt(2, ActivityEvent.ACTIVITY_REAL_DISPATCHED);
				pstmt.setString(3, packageId);
				pstmt.setString(4, processId);
				pstmt.setString(5, caseId);
				pstmt.setString(6, src_owner_process_id);
				pstmt.setString(7, src_activity_id);
				JDBCUtilities.cleanupNoThrow(pstmt);
				pstmt = null;
			}
		}
		catch (SQLException e)
		{
			WorkflowException ex = new WorkflowException("can not submit workflow work (XOR_JOIN)");
			ex.setRootCause(e);
			throw ex;
		}
		finally
		{
			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;

		}
		if (eventResult.isFirst())
		{
			String xorJoinWorkId = eventResult.getJoinWorkUUID();
			WorkflowWork xorJoinWork =
				caseDatabase.findWork(workflowsession, userTransaction, workflowProcess, work.getCase(), xorJoinWorkId);
			caseDatabase.createPath(
				workflowsession,
				userTransaction,
				workflowProcess,
				work.getCase(),
				work,
				xorJoinWork,
				pathSubmitBatch,
				WorkEvent.SUBMITED);

			return ControllerDispatcher.executeDispatchIfNecessary(
				workflowsession,
				workflowtemplate,
				userTransaction,
				workflowProcess,
				xorJoinWork,
				userObject);
		}
		else
		{
			//忽略非第一个完成的前继任务??? FIXME!!!!
		}
		return true;

	}

	protected static boolean submit_orJoin(
		WorkflowSession workflowsession,
		WorkflowXPDL workflowtemplate,
		WorkflowTransaction userTransaction,
		WorkflowProcess workflowProcess,
		WorkflowWork work,
		WorkflowTransition workflowTransition,
		String pathSubmitBatch,
		Map userObject)
		throws WorkflowException, InterruptedException
	{
		log.debug("workitem ==> " + work + " || transition ==> " + workflowTransition);
		WorkflowCaseDatabase caseDatabase = workflowtemplate.getWorkflowTemplate().getCaseDatabase();
		EventQueue eventQueue = caseDatabase.getWorkflowTemplate().getOwnerWorkflowXPDL().getEventQueue();
		JoinEvent monitorEvent =
			new JoinEvent(
				work,
				JoinEvent.JOIN_OR,
				workflowsession,
				workflowtemplate,
				userTransaction,
				workflowProcess,
				workflowTransition,
				userObject);
		eventQueue.postEvent(monitorEvent);

		JoinEventGuard eventResult = monitorEvent.getJoinEventGuard();

		if (eventResult.getJoinException() != null)
		{
			eventResult.getJoinException().printStackTrace();
			throw new WorkflowException(eventResult.getJoinException());
		}

		Connection conn = userTransaction.getConnection();
		PreparedStatement pstmt = null;
		String strSQL = null;
		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();

		//log.debug("\norJoin monitorEvent == > " + monitorEvent);

		try
		{
			if (eventResult.getDispatchCount() == 0)
			{
				strSQL =
					"INSERT INTO  "
						+ caseDatabase.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, src_owner_process_id);
				pstmt.setString(5, src_activity_id);
				pstmt.setInt(6, eventResult.getDispatchCount() + 1);
				pstmt.execute();

				JDBCUtilities.cleanupNoThrow(pstmt);
				pstmt = null;
			}
			else
			{
				strSQL =
					"UPDATE "
						+ caseDatabase.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, eventResult.getDispatchCount() + 1);
				pstmt.setInt(2, ActivityEvent.ACTIVITY_REAL_DISPATCHED);
				pstmt.setString(3, packageId);
				pstmt.setString(4, processId);
				pstmt.setString(5, caseId);
				pstmt.setString(6, src_owner_process_id);
				pstmt.setString(7, src_activity_id);
				JDBCUtilities.cleanupNoThrow(pstmt);
				pstmt = null;
			}
		}
		catch (SQLException e)
		{
			WorkflowException ex = new WorkflowException("can not submit workflow work (TO OR_JOIN)");
			ex.setRootCause(e);
			throw ex;
		}
		finally
		{
			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;

		}
		String orJoinWorkId = eventResult.getJoinWorkUUID();
		WorkflowWork orJoinWork =
			caseDatabase.findWork(workflowsession, userTransaction, workflowProcess, work.getCase(), orJoinWorkId);
		caseDatabase.createPath(
			workflowsession,
			userTransaction,
			workflowProcess,
			work.getCase(),
			work,
			orJoinWork,
			pathSubmitBatch,
			WorkEvent.SUBMITED);

		if (eventResult.isLast())
		{
			return ControllerDispatcher.executeDispatchIfNecessary(
				workflowsession,
				workflowtemplate,
				userTransaction,
				workflowProcess,
				orJoinWork,
				userObject);
		}
		return true;
	}

	protected static boolean submit_routeJoin(
		WorkflowSession workflowsession,
		WorkflowXPDL workflowtemplate,
		WorkflowTransaction userTransaction,
		WorkflowProcess workflowProcess,
		WorkflowWork work,
		WorkflowTransition workflowTransition,
		String pathSubmitBatch,
		Map userObject)
		throws WorkflowException
	{
		log.debug("workitem ==> " + work + " || transition ==> " + workflowTransition);

		return CommonDispatcher.submit_general(
			workflowsession,
			workflowtemplate,
			userTransaction,
			workflowProcess,
			work,
			workflowTransition,
			pathSubmitBatch,
			null);
	}

	protected static boolean submit_instanceAndJoin(
		WorkflowSession workflowsession,
		WorkflowXPDL workflowtemplate,
		WorkflowTransaction userTransaction,
		WorkflowProcess workflowProcess,
		WorkflowWork work,
		WorkflowTransition workflowTransition,
		String pathSubmitBatch,
		Map userObject)
		throws WorkflowException, InterruptedException
	{
		log.debug("workitem ==> " + work + " || transition ==> " + workflowTransition);
		WorkflowCaseDatabase caseDatabase = workflowtemplate.getWorkflowTemplate().getCaseDatabase();
		EventQueue eventQueue = caseDatabase.getWorkflowTemplate().getOwnerWorkflowXPDL().getEventQueue();
		JoinEvent monitorEvent =
			new JoinEvent(
				work,
				JoinEvent.JOIN_INSTANCE_AND,
				workflowsession,
				workflowtemplate,
				userTransaction,
				workflowProcess,
				workflowTransition,
				userObject);
		eventQueue.postEvent(monitorEvent);

		JoinEventGuard eventResult = monitorEvent.getJoinEventGuard();

		if (eventResult.getJoinException() != null)
		{
			throw new WorkflowException(eventResult.getJoinException());
		}

		Connection conn = userTransaction.getConnection();
		PreparedStatement pstmt = null;
		String strSQL = null;
		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();

		log.debug("\ninstanceAndJoin monitorEvent == > " + monitorEvent);

		try
		{
			if (eventResult.getDispatchCount() == 0)
			{
				strSQL =
					"INSERT INTO  "
						+ caseDatabase.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, src_owner_process_id);
				pstmt.setString(5, src_activity_id);
				pstmt.setInt(6, eventResult.getDispatchCount() + 1);
				pstmt.execute();

				JDBCUtilities.cleanupNoThrow(pstmt);
				pstmt = null;
			}
			else
			{
				strSQL =
					"UPDATE "
						+ caseDatabase.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, eventResult.getDispatchCount() + 1);
				pstmt.setInt(2, ActivityEvent.ACTIVITY_REAL_DISPATCHED);
				pstmt.setString(3, packageId);
				pstmt.setString(4, processId);
				pstmt.setString(5, caseId);
				pstmt.setString(6, src_owner_process_id);
				pstmt.setString(7, src_activity_id);
				JDBCUtilities.cleanupNoThrow(pstmt);
				pstmt = null;
			}
		}
		catch (SQLException e)
		{
			WorkflowException ex = new WorkflowException("can not submit workflow work (TO INSTANCE_AND_JOIN)");
			ex.setRootCause(e);
			throw ex;
		}
		finally
		{
			JDBCUtilities.cleanupNoThrow(pstmt);
			pstmt = null;
		}

		String andJoinWorkUUID = eventResult.getJoinWorkUUID();
		WorkflowWork andJoinWork =
			caseDatabase.findWork(workflowsession, userTransaction, workflowProcess, work.getCase(), andJoinWorkUUID);
		caseDatabase.createPath(
			workflowsession,
			userTransaction,
			workflowProcess,
			work.getCase(),
			work,
			andJoinWork,
			pathSubmitBatch,
			WorkEvent.SUBMITED);

		if (eventResult.isLast())
		{
			return ControllerDispatcher.executeDispatchIfNecessary(
				workflowsession,
				workflowtemplate,
				userTransaction,
				workflowProcess,
				andJoinWork,
				userObject);
		}

		return true;
	}

	protected static boolean submit_instanceXorJoin(
		WorkflowSession workflowsession,
		WorkflowXPDL workflowtemplate,
		WorkflowTransaction userTransaction,
		WorkflowProcess workflowProcess,
		WorkflowWork work,
		WorkflowTransition workflowTransition,
		String pathSubmitBatch,
		Map userObject)
		throws WorkflowException, InterruptedException
	{
		log.debug("workitem ==> " + work + " || transition ==> " + workflowTransition);
		WorkflowCaseDatabase caseDatabase = workflowtemplate.getWorkflowTemplate().getCaseDatabase();
		EventQueue eventQueue = caseDatabase.getWorkflowTemplate().getOwnerWorkflowXPDL().getEventQueue();
		JoinEvent monitorEvent =
			new JoinEvent(
				work,
				JoinEvent.JOIN_INSTANCE_XOR,
				workflowsession,
				workflowtemplate,
				userTransaction,
				workflowProcess,
				workflowTransition,
				userObject);
		eventQueue.postEvent(monitorEvent);

		JoinEventGuard eventResult = monitorEvent.getJoinEventGuard();

		if (eventResult.getJoinException() != null)
		{
			throw new WorkflowException(eventResult.getJoinException());
		}

		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();

		//log.debug("\ninstanceXorJoin monitorEvent == > " + monitorEvent);

		if (eventResult.isFirst())
		{
			String xor_work_id = eventResult.getJoinWorkUUID();
			WorkflowWork xorJoinWork =
				caseDatabase.findWork(workflowsession, userTransaction, workflowProcess, work.getCase(), xor_work_id);

			String batchNo = workflowtemplate.getWorkflowTemplate().getUUIDGenerator().nextBatchUUID(work);
			caseDatabase.createPath(
				workflowsession,
				userTransaction,
				workflowProcess,
				work.getCase(),
				work,
				xorJoinWork,
				batchNo,
				WorkEvent.SUBMITED);

			return ControllerDispatcher.executeDispatchIfNecessary(
				workflowsession,
				workflowtemplate,
				userTransaction,
				workflowProcess,
				xorJoinWork,
				userObject);
		}

		return true;
	}

	protected static boolean submit_weightJoin(
		WorkflowSession workflowsession,
		WorkflowXPDL workflowtemplate,
		WorkflowTransaction userTransaction,
		WorkflowProcess workflowProcess,
		WorkflowWork work,
		WorkflowTransition workflowTransition,
		String pathSubmitBatch,
		Map userObject)
		throws WorkflowException
	{
		log.debug("workitem ==> " + work + " || transition ==> " + workflowTransition);

		//-------------------------------------------
		// reserved for extenstion,not supported now
		//-------------------------------------------
		return true;
	}

	protected static boolean submit_instanceWeightJoin(
		WorkflowSession workflowsession,
		WorkflowXPDL workflowtemplate,
		WorkflowTransaction userTransaction,
		WorkflowProcess workflowProcess,
		WorkflowWork work,
		WorkflowTransition workflowTransition,
		String pathSubmitBatch,
		Map userObject)
		throws WorkflowException
	{
		log.debug("workitem ==> " + work + " || transition ==> " + workflowTransition);

		//-------------------------------------------
		// reserved for extenstion,not supported now
		//-------------------------------------------
		return true;
	}
}
