/*****************************************************************************/
        /************                                                        **********/
        /************            task instance 相关的持久化方法               **********/
        /************            Persistence methods for task instance       **********/
        /************                                                        **********/
        /******************************************************************************/

        /// <summary>
        /// <para>插入或者更新TaskInstance。</para>
        /// <para>Save or update task instance. If the taskInstance.id is null then insert a new task instance record</para>
        /// <para>and generate a new id for it { throw new NotImplementedException(); }</para>
        /// <para>otherwise update the existent one. </para>
        /// </summary>
        public bool SaveOrUpdateTaskInstance(ITaskInstance taskInstance)
        {
            if (String.IsNullOrEmpty(taskInstance.Id))
            {
                ((TaskInstance)taskInstance).Id = Guid.NewGuid().ToString().Replace("-", "");
                string insert = "INSERT INTO T_FF_RT_TASKINSTANCE (" +
                "ID, BIZ_TYPE, TASK_ID, ACTIVITY_ID, NAME, " +
                "DISPLAY_NAME, STATE, SUSPENDED, TASK_TYPE, CREATED_TIME, " +
                "STARTED_TIME, EXPIRED_TIME, END_TIME, ASSIGNMENT_STRATEGY, PROCESSINSTANCE_ID, " +
                "PROCESS_ID, VERSION, TARGET_ACTIVITY_ID, FROM_ACTIVITY_ID, STEP_NUMBER, " +
                "CAN_BE_WITHDRAWN, BIZ_INFO )VALUES(@1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @11, @12, @13, @14, @15, @16, @17, @18, @19, @20, @21, @22)";
                SqlParameter[] insertParms = { 
    				SqlServerHelper.NewSqlParameter("@1", SqlDbType.VarChar, 50, taskInstance.Id), 
    				SqlServerHelper.NewSqlParameter("@2", SqlDbType.VarChar, 250, taskInstance.GetType().Name), 
    				SqlServerHelper.NewSqlParameter("@3", SqlDbType.VarChar, 300, taskInstance.TaskId), 
    				SqlServerHelper.NewSqlParameter("@4", SqlDbType.VarChar, 200, taskInstance.ActivityId), 
    				SqlServerHelper.NewSqlParameter("@5", SqlDbType.VarChar, 100, taskInstance.Name), 
    				SqlServerHelper.NewSqlParameter("@6", SqlDbType.VarChar, 128, taskInstance.DisplayName), 
    				SqlServerHelper.NewSqlParameter("@7", SqlDbType.Int, (int)taskInstance.State), 
    				SqlServerHelper.NewSqlParameter("@8", SqlDbType.SmallInt, SqlServerHelper.OraBit(taskInstance.IsSuspended())), 
    				SqlServerHelper.NewSqlParameter("@9", SqlDbType.VarChar, 10, taskInstance.TaskType), 
    				SqlServerHelper.NewSqlParameter("@10", SqlDbType.DateTime, 11, taskInstance.CreatedTime), 
    				SqlServerHelper.NewSqlParameter("@11", SqlDbType.DateTime, 11, taskInstance.StartedTime), 
    				SqlServerHelper.NewSqlParameter("@12", SqlDbType.DateTime, 11, taskInstance.ExpiredTime), 
    				SqlServerHelper.NewSqlParameter("@13", SqlDbType.DateTime, 11, taskInstance.EndTime), 
    				SqlServerHelper.NewSqlParameter("@14", SqlDbType.VarChar, 10, taskInstance.AssignmentStrategy), 
    				SqlServerHelper.NewSqlParameter("@15", SqlDbType.VarChar, 50, taskInstance.ProcessInstanceId), 
    				SqlServerHelper.NewSqlParameter("@16", SqlDbType.VarChar, 100, taskInstance.ProcessId), 
    				SqlServerHelper.NewSqlParameter("@17", SqlDbType.Int, taskInstance.Version), 
    				SqlServerHelper.NewSqlParameter("@18", SqlDbType.VarChar, 100, taskInstance.TargetActivityId), 
    				SqlServerHelper.NewSqlParameter("@19", SqlDbType.VarChar, 600, ((TaskInstance) taskInstance).FromActivityId), 
    				SqlServerHelper.NewSqlParameter("@20", SqlDbType.Int, taskInstance.StepNumber), 
    				SqlServerHelper.NewSqlParameter("@21", SqlDbType.SmallInt, SqlServerHelper.OraBit(((TaskInstance) taskInstance).CanBeWithdrawn)),
    				SqlServerHelper.NewSqlParameter("@22", SqlDbType.VarChar, 500, taskInstance.BizInfo)
    			};
                if (SqlServerHelper.ExecuteNonQuery(connectionString, CommandType.Text, insert, insertParms) != 1)
                    return false;
                else return true;
            }
            else
            {
                string update = "UPDATE T_FF_RT_TASKINSTANCE SET " +
                "BIZ_TYPE=@2, TASK_ID=@3, ACTIVITY_ID=@4, NAME=@5, DISPLAY_NAME=@6, " +
                "STATE=@7, SUSPENDED=@8, TASK_TYPE=@9, CREATED_TIME=@10, STARTED_TIME=@11, " +
                "EXPIRED_TIME=@12, END_TIME=@13, ASSIGNMENT_STRATEGY=@14, PROCESSINSTANCE_ID=@15, PROCESS_ID=@16, " +
                "VERSION=@17, TARGET_ACTIVITY_ID=@18, FROM_ACTIVITY_ID=@19, STEP_NUMBER=@20, CAN_BE_WITHDRAWN=@21, BIZ_INFO=@22" +
                " WHERE ID=@1";
                SqlParameter[] updateParms = { 
    				SqlServerHelper.NewSqlParameter("@2", SqlDbType.VarChar, 250, taskInstance.GetType().Name), 
    				SqlServerHelper.NewSqlParameter("@3", SqlDbType.VarChar, 300, taskInstance.TaskId), 
    				SqlServerHelper.NewSqlParameter("@4", SqlDbType.VarChar, 200, taskInstance.ActivityId), 
    				SqlServerHelper.NewSqlParameter("@5", SqlDbType.VarChar, 100, taskInstance.Name), 
    				SqlServerHelper.NewSqlParameter("@6", SqlDbType.VarChar, 128, taskInstance.DisplayName), 
    				SqlServerHelper.NewSqlParameter("@7", SqlDbType.Int, (int)taskInstance.State), 
    				SqlServerHelper.NewSqlParameter("@8", SqlDbType.SmallInt, SqlServerHelper.OraBit(taskInstance.IsSuspended())), 
    				SqlServerHelper.NewSqlParameter("@9", SqlDbType.VarChar, 10, taskInstance.TaskType), 
    				SqlServerHelper.NewSqlParameter("@10", SqlDbType.DateTime, 11, taskInstance.CreatedTime), 
    				SqlServerHelper.NewSqlParameter("@11", SqlDbType.DateTime, 11, taskInstance.StartedTime), 
    				SqlServerHelper.NewSqlParameter("@12", SqlDbType.DateTime, 11, taskInstance.ExpiredTime), 
    				SqlServerHelper.NewSqlParameter("@13", SqlDbType.DateTime, 11, taskInstance.EndTime), 
    				SqlServerHelper.NewSqlParameter("@14", SqlDbType.VarChar, 10, taskInstance.AssignmentStrategy), 
    				SqlServerHelper.NewSqlParameter("@15", SqlDbType.VarChar, 50, taskInstance.ProcessInstanceId), 
    				SqlServerHelper.NewSqlParameter("@16", SqlDbType.VarChar, 100, taskInstance.ProcessId), 
    				SqlServerHelper.NewSqlParameter("@17", SqlDbType.Int, taskInstance.Version), 
    				SqlServerHelper.NewSqlParameter("@18", SqlDbType.VarChar, 100, taskInstance.TargetActivityId), 
    				SqlServerHelper.NewSqlParameter("@19", SqlDbType.VarChar, 600, ((TaskInstance) taskInstance).FromActivityId), 
    				SqlServerHelper.NewSqlParameter("@20", SqlDbType.Int, taskInstance.StepNumber), 
    				SqlServerHelper.NewSqlParameter("@21", SqlDbType.SmallInt, SqlServerHelper.OraBit(((TaskInstance) taskInstance).CanBeWithdrawn)),
    				SqlServerHelper.NewSqlParameter("@22", SqlDbType.VarChar, 500, taskInstance.BizInfo),
    				SqlServerHelper.NewSqlParameter("@1", SqlDbType.VarChar, 50, taskInstance.Id)
    			};
                if (SqlServerHelper.ExecuteNonQuery(connectionString, CommandType.Text, update, updateParms) != 1)
                    return false;
                else return true;
            }
        }
        /// <summary>
        /// 终止当前TaskInstance,检查是否可以中止当前ActivityInstance,如果可以,
        /// 则结束当前ActivityInstance,并触发targetActivityInstance或后继ActivityInstance
        /// </summary>
        /// <param name="currentSession"></param>
        /// <param name="processInstance"></param>
        /// <param name="taskInstance"></param>
        /// <param name="targetActivityInstance"></param>
        public void completeTaskInstance(IWorkflowSession currentSession, IProcessInstance processInstance,
            ITaskInstance taskInstance, IActivityInstance targetActivityInstance)
        {
            //如果TaskInstance处于结束状态,则直接返回
            if (taskInstance.State == TaskInstanceStateEnum.COMPLETED || taskInstance.State == TaskInstanceStateEnum.CANCELED)
            {
                return;
            }
            if (taskInstance.State == TaskInstanceStateEnum.INITIALIZED)
            {
                WorkflowProcess process = taskInstance.WorkflowProcess;
                throw new EngineException(taskInstance.ProcessInstanceId, process,
                        taskInstance.TaskId,
                        "Complete task insatance failed.The state of the task insatnce[id=" + taskInstance.Id + "] is " + taskInstance.State);
            }
            if (taskInstance.IsSuspended())
            {
                WorkflowProcess process = taskInstance.WorkflowProcess;
                throw new EngineException(taskInstance.ProcessInstanceId, process,
                        taskInstance.TaskId,
                        "Complete task insatance failed. The task instance [id=" + taskInstance.Id + "] is suspended");
            }

            if (targetActivityInstance != null)
            {
                ((TaskInstance)taskInstance).TargetActivityId=targetActivityInstance.Activity.Id;
            }

            IPersistenceService persistenceService = this.RuntimeContext.PersistenceService;

            //第一步,首先结束当前taskInstance
            if (!this.taskInstanceCanBeCompleted(currentSession, this.RuntimeContext, processInstance, taskInstance))
            {
                return;
            }
            ((TaskInstance)taskInstance).State=TaskInstanceStateEnum.COMPLETED;
            ((TaskInstance)taskInstance).CanBeWithdrawn=false;
            ((TaskInstance)taskInstance).EndTime=RuntimeContext.CalendarService.getSysDate();
            persistenceService.SaveOrUpdateTaskInstance(taskInstance);
            //触发相应的事件
            TaskInstanceEvent e = new TaskInstanceEvent();
            e.Source=taskInstance;
            e.WorkflowSession=currentSession;
            e.ProcessInstance=processInstance;
            e.EventType = TaskInstanceEventEnum.AFTER_TASK_INSTANCE_COMPLETE;
            if (this.DefaultTaskInstanceEventListener != null)
            {
                this.DefaultTaskInstanceEventListener.onTaskInstanceEventFired(e);
            }

            this.fireTaskInstanceEvent(taskInstance, e);

            //第二步,检查ActivityInstance是否可以结束
            if (!activityInstanceCanBeCompleted(taskInstance))
            {
                return;
            }

            //第三步,尝试结束对应的activityInstance
            List<IToken> tokens = persistenceService.FindTokensForProcessInstance(taskInstance.ProcessInstanceId, taskInstance.ActivityId);
            //        System.out.println("Inside TaskInstance.complete(targetActivityInstance):: tokens.size is "+tokens.Count);
            if (tokens == null || tokens.Count == 0)
            {
                return;//表明activityInstance已经结束了。
            }
            if (tokens.Count > 1)
            {
                WorkflowProcess process = taskInstance.WorkflowProcess;
                throw new EngineException(taskInstance.ProcessInstanceId, process, taskInstance.TaskId,
                        "与activityId=" + taskInstance.ActivityId + "对应的token数量(=" + tokens.Count + ")不正确,正确只能为1,因此无法完成complete操作");
            }
            IToken token = tokens[0];
            //stepNumber不相等,不允许执行结束操作。
            if (token.StepNumber != taskInstance.StepNumber)
            {
                return;
            }
            if (token.IsAlive == false)
            {
                WorkflowProcess process = taskInstance.WorkflowProcess;
                throw new EngineException(taskInstance.ProcessInstanceId, process,
                        taskInstance.TaskId,
                        "与activityId=" + taskInstance.ActivityId + "对应的token.alive=false,因此无法完成complete操作");
            }

            INetInstance netInstance = this.RuntimeContext.KernelManager.getNetInstance(taskInstance.ProcessId, taskInstance.Version);
            Object obj = netInstance.getWFElementInstance(taskInstance.ActivityId);
            if (obj == null)
            {
                WorkflowProcess process = taskInstance.WorkflowProcess;
                throw new EngineException(taskInstance.ProcessInstanceId, process, taskInstance.TaskId,
                        "系统没有找到与activityId=" + taskInstance.ActivityId + "对应activityInstance,无法执行complete操作。");
            }

            token.ProcessInstance = processInstance;

            ((IActivityInstance)obj).complete(token, targetActivityInstance);
        }
        /// <summary>
        /// 中止当前的TaskInstance,并使得流程流转到指定的环节。
        /// </summary>
        /// <param name="currentSession"></param>
        /// <param name="processInstance"></param>
        /// <param name="taskInstance"></param>
        /// <param name="targetActivityId"></param>
        public void abortTaskInstance(IWorkflowSession currentSession,
            IProcessInstance processInstance, ITaskInstance taskInstance,
            String targetActivityId)
        {
            // 如果TaskInstance处于结束状态,则直接返回
            if (taskInstance.State == TaskInstanceStateEnum.COMPLETED || taskInstance.State == TaskInstanceStateEnum.CANCELED)
            {
                return;
            }
            // Initialized状态的TaskInstance也可以中止,20090830
            // if (taskInstance.State == ITaskInstance.INITIALIZED) {
            // WorkflowProcess process = taskInstance.getWorkflowProcess();
            // throw new EngineException(taskInstance.getProcessInstanceId(),
            // process,
            // taskInstance.getTaskId(),
            // "Complete task insatance failed.The state of the task insatnce[id=" +
            // taskInstance.getId() + "] is " + taskInstance.State);
            // }
            if (taskInstance.IsSuspended())
            {
                WorkflowProcess process = taskInstance.WorkflowProcess;
                throw new EngineException(taskInstance.ProcessInstanceId,
                        process, taskInstance.TaskId,
                        "Abort task insatance failed. The task instance [id="
                                + taskInstance.Id + "] is suspended");
            }

            // 1)检查是否在同一个“执行线”上
            WorkflowProcess workflowProcess = taskInstance.WorkflowProcess;
            if (targetActivityId != null)
            {
                String thisActivityId = taskInstance.ActivityId;
                Boolean isInSameLine = workflowProcess.isInSameLine(thisActivityId,
                        targetActivityId);
                if (!isInSameLine)
                {
                    throw new EngineException(
                            taskInstance.ProcessInstanceId,
                            taskInstance.WorkflowProcess,
                            taskInstance.TaskId,
                            "Jumpto refused because of the current activitgy and the target activity are NOT in the same 'Execution Thread'.");
                }
            }

            INetInstance netInstance = this.RuntimeContext.KernelManager.getNetInstance(workflowProcess.Id, taskInstance.Version);
            IActivityInstance targetActivityInstance = (IActivityInstance)netInstance.getWFElementInstance(targetActivityId);

            IActivityInstance thisActivityInstance = (IActivityInstance)netInstance.getWFElementInstance(taskInstance.ActivityId);
            if (thisActivityInstance == null)
            {
                WorkflowProcess process = taskInstance.WorkflowProcess;
                throw new EngineException(taskInstance.ProcessInstanceId, process, taskInstance.TaskId,
                    "系统没有找到与activityId=" + taskInstance.ActivityId + "对应activityInstance,无法执行abort操作。");
            }

            if (targetActivityInstance != null)
            {
                ((TaskInstance)taskInstance).TargetActivityId=targetActivityInstance.Activity.Id;
            }

            IPersistenceService persistenceService = this.RuntimeContext.PersistenceService;

            // 第一步,首先Abort当前taskInstance
            persistenceService.AbortTaskInstance((TaskInstance)taskInstance);

            // 触发相应的事件
            TaskInstanceEvent e = new TaskInstanceEvent();
            e.Source=taskInstance;
            e.WorkflowSession=currentSession;
            e.ProcessInstance=processInstance;
            e.EventType = TaskInstanceEventEnum.AFTER_TASK_INSTANCE_COMPLETE;
            if (this.DefaultTaskInstanceEventListener != null)
            {
                this.DefaultTaskInstanceEventListener.onTaskInstanceEventFired(e);
            }

            this.fireTaskInstanceEvent(taskInstance, e);

            // 第二步,检查ActivityInstance是否可以结束
            if (!activityInstanceCanBeCompleted(taskInstance))
            {
                return;
            }

            // 第三步,尝试结束对应的activityInstance
            List<IToken> tokens = persistenceService.FindTokensForProcessInstance(taskInstance.ProcessInstanceId, taskInstance.ActivityId);
            // System.out.println("Inside TaskInstance.complete(targetActivityInstance):: tokens.size is "+tokens.size());
            if (tokens == null || tokens.Count == 0)
            {
                return;// 表明activityInstance已经结束了。
            }
            if (tokens.Count > 1)
            {
                WorkflowProcess process = taskInstance.WorkflowProcess;
                throw new EngineException(taskInstance.ProcessInstanceId, process, taskInstance.TaskId,
                    "与activityId=" + taskInstance.ActivityId + "对应的token数量(=" + tokens.Count + ")不正确,正确只能为1,因此无法完成complete操作");
            }
            IToken token = tokens[0];
            // stepNumber不相等,不允许执行结束操作。
            if (token.StepNumber != taskInstance.StepNumber)
            {
                return;
            }
            if (token.IsAlive == false)
            {
                WorkflowProcess process = taskInstance.WorkflowProcess;
                throw new EngineException(taskInstance.ProcessInstanceId, process, taskInstance.TaskId,
                    "与activityId=" + taskInstance.ActivityId + "对应的token.alive=false,因此无法完成complete操作");
            }

            token.ProcessInstance = processInstance;

            thisActivityInstance.complete(token, targetActivityInstance);
        }
        public void abortTaskInstanceEx(IWorkflowSession currentSession, IProcessInstance processInstance, 
            ITaskInstance thisTaskInst, String targetActivityId)
        {
            // 如果TaskInstance处于结束状态,则直接返回
            if (thisTaskInst.State == TaskInstanceStateEnum.COMPLETED || thisTaskInst.State == TaskInstanceStateEnum.CANCELED)
            {
                return;
            }

            // Initialized状态的TaskInstance也可以中止,20090830
            // if (taskInstance.State == ITaskInstance.INITIALIZED) {
            // WorkflowProcess process = taskInstance.getWorkflowProcess();
            // throw new EngineException(taskInstance.getProcessInstanceId(),
            // process,
            // taskInstance.getTaskId(),
            // "Complete task insatance failed.The state of the task insatnce[id=" +
            // taskInstance.getId() + "] is " + taskInstance.State);
            // }
            if (thisTaskInst.IsSuspended())
            {
                WorkflowProcess process = thisTaskInst.WorkflowProcess;
                throw new EngineException(thisTaskInst.ProcessInstanceId,
                        process, thisTaskInst.TaskId,
                        "Abort task insatance failed. The task instance [id="
                                + thisTaskInst.Id + "] is suspended");
            }

            //
            IPersistenceService persistenceService = this.RuntimeContext.PersistenceService;
            WorkflowProcess workflowProcess = thisTaskInst.WorkflowProcess;
            List<IToken> allTokens = null;
            List<String> aliveActivityIdsAfterJump = new List<String>();
            if (targetActivityId != null)
            {
                String thisActivityId = thisTaskInst.ActivityId;
                Boolean isInSameLine = workflowProcess.isInSameLine(thisActivityId, targetActivityId);

                if (isInSameLine)
                {
                    this.abortTaskInstance(currentSession, processInstance, thisTaskInst, targetActivityId);
                }

                //合法性检查
                allTokens = persistenceService.FindTokensForProcessInstance(thisTaskInst.ProcessInstanceId, null);

                aliveActivityIdsAfterJump.Add(targetActivityId);

                for (int i = 0; allTokens != null && i < allTokens.Count; i++)
                {
                    IToken tokenTmp = allTokens[i];
                    IWFElement workflowElement = workflowProcess.findWFElementById(tokenTmp.NodeId);
                    if ((workflowElement is Activity) && !workflowElement.Id.Equals(thisActivityId))
                    {
                        aliveActivityIdsAfterJump.Add(workflowElement.Id);

                        if (workflowProcess.isReachable(targetActivityId, workflowElement.Id)
                            || workflowProcess.isReachable(workflowElement.Id, targetActivityId))
                        {
                            throw new EngineException(
                                    thisTaskInst.ProcessInstanceId,
                                    thisTaskInst.WorkflowProcess,
                                    thisTaskInst.TaskId,
                                    "Abort refused because of the business-logic conflict!");

                        }
                    }
                }

                //1)检查是否在同一个“执行线”上(不做该检查,20091008)
                //			if (!isInSameLine) {
                //				throw new EngineException(
                //						taskInstance.getProcessInstanceId(),
                //						taskInstance.getWorkflowProcess(),
                //						taskInstance.getTaskId(),
                //						"Jumpto refused because of the current activitgy and the target activity are NOT in the same 'Execution Thread'.");
                //			}
            }

            INetInstance netInstance = this.RuntimeContext.KernelManager.getNetInstance(workflowProcess.Id, thisTaskInst.Version);
            IActivityInstance targetActivityInstance = null;
            if (targetActivityId != null)
            {
                targetActivityInstance = (IActivityInstance)netInstance.getWFElementInstance(targetActivityId);
            }

            IActivityInstance thisActivityInstance = (IActivityInstance)netInstance.getWFElementInstance(thisTaskInst.ActivityId);
            if (thisActivityInstance == null)
            {
                WorkflowProcess process = thisTaskInst.WorkflowProcess;
                throw new EngineException(thisTaskInst.ProcessInstanceId, process, thisTaskInst.TaskId,
                    "系统没有找到与activityId=" + thisTaskInst.ActivityId + "对应activityInstance,无法执行abort操作。");
            }

            if (targetActivityInstance != null)
            {
                ((TaskInstance)thisTaskInst).TargetActivityId=targetActivityInstance.Activity.Id;
            }

            // 第一步,首先Abort当前taskInstance
            persistenceService.AbortTaskInstance((TaskInstance)thisTaskInst);

            // 触发相应的事件
            TaskInstanceEvent e = new TaskInstanceEvent();
            e.Source=thisTaskInst;
            e.WorkflowSession=currentSession;
            e.ProcessInstance=processInstance;
            e.EventType = TaskInstanceEventEnum.AFTER_TASK_INSTANCE_COMPLETE;
            if (this.DefaultTaskInstanceEventListener != null)
            {
                this.DefaultTaskInstanceEventListener.onTaskInstanceEventFired(e);
            }

            this.fireTaskInstanceEvent(thisTaskInst, e);

            // 第二步,检查ActivityInstance是否可以结束
            if (!activityInstanceCanBeCompleted(thisTaskInst))
            {
                return;
            }

            // 第三步,尝试结束对应的activityInstance
            List<IToken> tokens = persistenceService.FindTokensForProcessInstance(thisTaskInst.ProcessInstanceId, thisTaskInst.ActivityId);
            // System.out.println("Inside TaskInstance.complete(targetActivityInstance):: tokens.size is "+tokens.size());
            if (tokens == null || tokens.Count == 0)
            {
                return;// 表明activityInstance已经结束了。
            }
            if (tokens.Count > 1)
            {
                WorkflowProcess process = thisTaskInst.WorkflowProcess;
                throw new EngineException(thisTaskInst.ProcessInstanceId, process, thisTaskInst.TaskId,
                    "与activityId=" + thisTaskInst.ActivityId + "对应的token数量(=" + tokens.Count + ")不正确,正确只能为1,因此无法完成complete操作");
            }
            IToken token = tokens[0];
            // stepNumber不相等,不允许执行结束操作。
            if (token.StepNumber != thisTaskInst.StepNumber)
            {
                return;
            }
            if (token.IsAlive == false)
            {
                WorkflowProcess process = thisTaskInst.WorkflowProcess;
                throw new EngineException(thisTaskInst.ProcessInstanceId, process, thisTaskInst.TaskId,
                    "与activityId=" + thisTaskInst.ActivityId + "对应的token.alive=false,因此无法完成complete操作");
            }

            token.ProcessInstance = processInstance;

            //调整token布局
            if (targetActivityId != null)
            {
                List<Synchronizer> allSynchronizersAndEnds = new List<Synchronizer>();
                allSynchronizersAndEnds.AddRange(workflowProcess.Synchronizers);
                allSynchronizersAndEnds.AddRange((IEnumerable<Synchronizer>)workflowProcess.EndNodes.ToArray());
                //allSynchronizersAndEnds.AddRange((List<Synchronizer>));
                for (int i = 0; i < allSynchronizersAndEnds.Count; i++)
                {
                    Synchronizer synchronizer = allSynchronizersAndEnds[i];
                    if (synchronizer.Name.Equals("Synchronizer4"))
                    {
                        //System.out.println(synchronizer.Name);
                    }
                    int volumn = 0;
                    if (synchronizer is EndNode)
                    {
                        volumn = synchronizer.EnteringTransitions.Count;
                    }
                    else
                    {
                        volumn = synchronizer.EnteringTransitions.Count * synchronizer.LeavingTransitions.Count;
                    }
                    IToken tokenTmp = new Token();
                    tokenTmp.NodeId = synchronizer.Id;
                    tokenTmp.IsAlive = false;
                    tokenTmp.ProcessInstanceId = thisTaskInst.ProcessInstanceId;
                    tokenTmp.StepNumber = -1;

                    List<String> incomingTransitionIds = new List<String>();
                    Boolean reachable = false;
                    List<Transition> enteringTrans = synchronizer.EnteringTransitions;
                    for (int m = 0; m < aliveActivityIdsAfterJump.Count; m++)
                    {
                        String aliveActivityId = aliveActivityIdsAfterJump[m];
                        if (workflowProcess.isReachable(aliveActivityId, synchronizer.Id))
                        {
                            Transition trans = null;
                            reachable = true;
                            for (int j = 0; j < enteringTrans.Count; j++)
                            {
                                trans = enteringTrans[j];
                                Node fromNode = (Node)trans.FromNode;
                                if (workflowProcess.isReachable(aliveActivityId, fromNode.Id))
                                {
                                    if (!incomingTransitionIds.Contains(trans.Id))
                                    {
                                        incomingTransitionIds.Add(trans.Id);
                                    }
                                }
                            }
                        }
                    }
                    if (reachable)
                    {
                        tokenTmp.Value = volumn - (incomingTransitionIds.Count * volumn / enteringTrans.Count);

                        IToken virtualToken = getJoinInfo(allTokens, synchronizer.Id);

                        if (virtualToken != null)
                        {
                            persistenceService.DeleteTokensForNode(thisTaskInst.ProcessInstanceId, synchronizer.Id);
                        }

                        if (tokenTmp.Value != 0)
                        {
                            tokenTmp.ProcessInstance = processInstance;
                            persistenceService.SaveOrUpdateToken(tokenTmp);
                        }
                    }
                }
            }
            thisActivityInstance.complete(token, targetActivityInstance);
        }
        /*****************************************************************************/
        /************                                                        **********/
        /************            task instance 相关的持久化方法               **********/
        /************            Persistence methods for task instance       **********/
        /************                                                        **********/
        /******************************************************************************/

        /// <summary>
        /// <para>插入或者更新TaskInstance。</para>
        /// <para>Save or update task instance. If the taskInstance.id is null then insert a new task instance record</para>
        /// <para>and generate a new id for it { throw new NotImplementedException(); }</para>
        /// <para>otherwise update the existent one. </para>
        /// </summary>
        public bool SaveOrUpdateTaskInstance(ITaskInstance taskInstance)
        {
            if (String.IsNullOrEmpty(taskInstance.Id))
            {
                ((TaskInstance)taskInstance).Id = Guid.NewGuid().ToString().Replace("-", "");
                string insert = "INSERT INTO T_FF_RT_TASKINSTANCE (" +
                "ID, BIZ_TYPE, TASK_ID, ACTIVITY_ID, NAME, " +
                "DISPLAY_NAME, STATE, SUSPENDED, TASK_TYPE, CREATED_TIME, " +
                "STARTED_TIME, EXPIRED_TIME, END_TIME, ASSIGNMENT_STRATEGY, PROCESSINSTANCE_ID, " +
                "PROCESS_ID, VERSION, TARGET_ACTIVITY_ID, FROM_ACTIVITY_ID, STEP_NUMBER, " +
                "CAN_BE_WITHDRAWN, BIZ_INFO )VALUES(:1, :2, :3, :4, :5, :6, :7, :8, :9, :10, :11, :12, :13, :14, :15, :16, :17, :18, :19, :20, :21, :22)";
    			OracleParameter[] insertParms = { 
    				OracleHelper.NewOracleParameter(":1", OracleType.VarChar, 50, taskInstance.Id), 
    				OracleHelper.NewOracleParameter(":2", OracleType.VarChar, 250, taskInstance.GetType().Name), 
    				OracleHelper.NewOracleParameter(":3", OracleType.VarChar, 300, taskInstance.TaskId), 
    				OracleHelper.NewOracleParameter(":4", OracleType.VarChar, 200, taskInstance.ActivityId), 
    				OracleHelper.NewOracleParameter(":5", OracleType.VarChar, 100, taskInstance.Name), 
    				OracleHelper.NewOracleParameter(":6", OracleType.VarChar, 128, taskInstance.DisplayName), 
    				OracleHelper.NewOracleParameter(":7", OracleType.Int32, (int)taskInstance.State), 
    				OracleHelper.NewOracleParameter(":8", OracleType.Int16, OracleHelper.OraBit(taskInstance.IsSuspended())), 
    				OracleHelper.NewOracleParameter(":9", OracleType.VarChar, 10, taskInstance.TaskType), 
    				OracleHelper.NewOracleParameter(":10", OracleType.Timestamp, 11, taskInstance.CreatedTime), 
    				OracleHelper.NewOracleParameter(":11", OracleType.Timestamp, 11, taskInstance.StartedTime), 
    				OracleHelper.NewOracleParameter(":12", OracleType.Timestamp, 11, taskInstance.ExpiredTime), 
    				OracleHelper.NewOracleParameter(":13", OracleType.Timestamp, 11, taskInstance.EndTime), 
    				OracleHelper.NewOracleParameter(":14", OracleType.VarChar, 10, taskInstance.AssignmentStrategy), 
    				OracleHelper.NewOracleParameter(":15", OracleType.VarChar, 50, taskInstance.ProcessInstanceId), 
    				OracleHelper.NewOracleParameter(":16", OracleType.VarChar, 100, taskInstance.ProcessId), 
    				OracleHelper.NewOracleParameter(":17", OracleType.Int32, taskInstance.Version), 
    				OracleHelper.NewOracleParameter(":18", OracleType.VarChar, 100, taskInstance.TargetActivityId), 
    				OracleHelper.NewOracleParameter(":19", OracleType.VarChar, 600, ((TaskInstance) taskInstance).FromActivityId), 
    				OracleHelper.NewOracleParameter(":20", OracleType.Int32, taskInstance.StepNumber), 
    				OracleHelper.NewOracleParameter(":21", OracleType.Int16, OracleHelper.OraBit(((TaskInstance) taskInstance).CanBeWithdrawn)),
    				OracleHelper.NewOracleParameter(":22", OracleType.VarChar, 500, taskInstance.BizInfo)
    			};
    			if (OracleHelper.ExecuteNonQuery(connectionString, CommandType.Text, insert, insertParms) != 1)
    				return false;
    			else return true;
            }
            else
            {
                string update = "UPDATE T_FF_RT_TASKINSTANCE SET " +
                "BIZ_TYPE=:2, TASK_ID=:3, ACTIVITY_ID=:4, NAME=:5, DISPLAY_NAME=:6, " +
                "STATE=:7, SUSPENDED=:8, TASK_TYPE=:9, CREATED_TIME=:10, STARTED_TIME=:11, " +
                "EXPIRED_TIME=:12, END_TIME=:13, ASSIGNMENT_STRATEGY=:14, PROCESSINSTANCE_ID=:15, PROCESS_ID=:16, " +
                "VERSION=:17, TARGET_ACTIVITY_ID=:18, FROM_ACTIVITY_ID=:19, STEP_NUMBER=:20, CAN_BE_WITHDRAWN=:21, BIZ_INFO=:22" +
                " WHERE ID=:1";
                OracleParameter[] updateParms = { 
    				OracleHelper.NewOracleParameter(":2", OracleType.VarChar, 250, taskInstance.GetType().Name), 
    				OracleHelper.NewOracleParameter(":3", OracleType.VarChar, 300, taskInstance.TaskId), 
    				OracleHelper.NewOracleParameter(":4", OracleType.VarChar, 200, taskInstance.ActivityId), 
    				OracleHelper.NewOracleParameter(":5", OracleType.VarChar, 100, taskInstance.Name), 
    				OracleHelper.NewOracleParameter(":6", OracleType.VarChar, 128, taskInstance.DisplayName), 
    				OracleHelper.NewOracleParameter(":7", OracleType.Int32, (int)taskInstance.State), 
    				OracleHelper.NewOracleParameter(":8", OracleType.Int16, OracleHelper.OraBit(taskInstance.IsSuspended())), 
    				OracleHelper.NewOracleParameter(":9", OracleType.VarChar, 10, taskInstance.TaskType), 
    				OracleHelper.NewOracleParameter(":10", OracleType.Timestamp, 11, taskInstance.CreatedTime), 
    				OracleHelper.NewOracleParameter(":11", OracleType.Timestamp, 11, taskInstance.StartedTime), 
    				OracleHelper.NewOracleParameter(":12", OracleType.Timestamp, 11, taskInstance.ExpiredTime), 
    				OracleHelper.NewOracleParameter(":13", OracleType.Timestamp, 11, taskInstance.EndTime), 
    				OracleHelper.NewOracleParameter(":14", OracleType.VarChar, 10, taskInstance.AssignmentStrategy), 
    				OracleHelper.NewOracleParameter(":15", OracleType.VarChar, 50, taskInstance.ProcessInstanceId), 
    				OracleHelper.NewOracleParameter(":16", OracleType.VarChar, 100, taskInstance.ProcessId), 
    				OracleHelper.NewOracleParameter(":17", OracleType.Int32, taskInstance.Version), 
    				OracleHelper.NewOracleParameter(":18", OracleType.VarChar, 100, taskInstance.TargetActivityId), 
    				OracleHelper.NewOracleParameter(":19", OracleType.VarChar, 600, ((TaskInstance) taskInstance).FromActivityId), 
    				OracleHelper.NewOracleParameter(":20", OracleType.Int32, taskInstance.StepNumber), 
    				OracleHelper.NewOracleParameter(":21", OracleType.Int16, OracleHelper.OraBit(((TaskInstance) taskInstance).CanBeWithdrawn)),
    				OracleHelper.NewOracleParameter(":22", OracleType.VarChar, 500, taskInstance.BizInfo),
    				OracleHelper.NewOracleParameter(":1", OracleType.VarChar, 50, taskInstance.Id)
    			};
                if (OracleHelper.ExecuteNonQuery(connectionString, CommandType.Text, update, updateParms) != 1)
                    return false;
                else return true;
            }
        }