/// <summary> /// Add initialized active transition to the collection of active transitions /// </summary> /// <param name="at"></param> private void AddActiveTransition(TaskShell at) { if (at.CorrelationId == null) throw new Exception("Correlation id required"); if (at.Tokens.Count == 0) throw new Exception("Cannot add a transition without tokens"); Debug.Assert(InstanceId == at.ProcessInstanceId); Debug.Assert(Definition.GetTask(at.TaskId) != null); //find shared transitions... IDictionary<string, TaskShell> sharedTrans = new Dictionary<string, TaskShell>(); foreach (string tid in at.Tokens) { Token t = GetToken(tid); foreach (string atid in t.ActiveTransitions) { if (!sharedTrans.ContainsKey(atid)) sharedTrans[atid] = GetActiveTransition(atid); } } List<TaskShell> strans = new List<TaskShell>(sharedTrans.Values); if (strans.Count > 0) { log.Info("Transition shares the same tokens with {0} active transitions."); if (strans.Count == 1) { strans[0].SharedId = strans[0].CorrelationId; } at.SharedId = strans[0].SharedId; foreach (TaskShell at2 in strans) Debug.Assert(at2.SharedId == at.SharedId); } Task tsk = Definition.GetTask(at.TaskId); _activeTransitions[at.CorrelationId] = at; IList<TaskShell> ats; if (!_activeTaskTransitions.TryGetValue(at.TaskId, out ats)) { ats = new List<TaskShell>(); _activeTaskTransitions[at.TaskId] = ats; } ats.Add(at); foreach (string tokid in at.Tokens) { Token tok = GetToken(tokid); tok.ActiveTransitions.Add(at.CorrelationId); } }
private TaskShell CreateActiveTransitionForTask(Task tsk) { TaskShell ts; if (tsk.IsMultiInstance) { ts = new MultiTaskShell(); } else { ts = new TaskShell(); } ts.TaskId = tsk.Id; ts.CorrelationId = GetNextTransitionId(); ts.SetProcessInstance(this); ts.ParentCallback = this; ts.EnvironmentContext = this.Environment; return ts; }
/// <summary> /// Create input data for transition by executing task input data bindings. /// TODO: Implement /// All task input variables have to be bound... /// 1. execute data bindings - get input variables in xml /// 2. validate the xml document /// 3. add local variables initial values /// </summary> /// <param name="at"></param> private void TransferDataToTransition(TaskShell at) { log.Debug("Transferring data to transition {0}", at.CorrelationId); at.TransferInputDataToTask(GetProcessDataSource()); }
/// <summary> /// This function is responsible for updating net status after transition has fired. /// It consumes transition input tokens and produces tokens in transition output places. /// Also, transition input conditions are evaluated before creating output tokens. /// </summary> /// <param name="at"></param> private void UpdateNetStatusAfterTransition(TaskShell at) { Task tsk = Definition.GetTask(at.TaskId); foreach (string tokid in at.Tokens) { Token tok = GetToken(tokid); Debug.Assert(tok.Status == TokenStatus.LOCKED_ALLOCATED); Debug.Assert(tok.ActiveTransitions.Count == 1); Debug.Assert(tok.ActiveTransitions[0] == at.CorrelationId); tok.Status = TokenStatus.CONSUMED; } IList<Token> newTokens = new List<Token>(); if (tsk.SplitType == JoinType.AND) { foreach (Flow fl in tsk.FlowsOut) { if (fl.InputCondition != null && fl.InputCondition.Length > 0) throw new Exception(); Token t = CreateNewTokenInPlace(fl.To.Id); newTokens.Add(t); } } else if (tsk.SplitType == JoinType.XOR) { IList<Flow> flows = tsk.FlowsOutOrdered; for (int i = 0; i < flows.Count; i++) { if (i == flows.Count - 1) //last flow - the default one { Token t = CreateNewTokenInPlace(flows[i].To.Id); log.Debug("Produced token in default flow: {0}, token: {1}", flows[i].ToString(), t.TokenId); newTokens.Add(t); } else { if (EvaluateFlowInputCondition(flows[i])) { Token t = CreateNewTokenInPlace(flows[i].To.Id); log.Debug("Produced token in flow: {0}, token: {1}", flows[i].ToString(), t.TokenId); newTokens.Add(t); break; } } } } else if (tsk.SplitType == JoinType.OR) { IList<Flow> flows = tsk.FlowsOutOrdered; for (int i = 0; i < flows.Count; i++) { if (EvaluateFlowInputCondition(flows[i])) { Token t = CreateNewTokenInPlace(flows[i].To.Id); log.Debug("Produced token in flow: {0}, token: {1}", flows[i].ToString(), t.TokenId); newTokens.Add(t); } } } else throw new Exception(); if (newTokens.Count == 0) throw new ApplicationException("No tokens were produced after transition " + at.CorrelationId); foreach (Token t in newTokens) { t.Status = TokenStatus.READY; AddToken(t); } }
/// <summary> /// Initiate task /// </summary> /// <param name="at"></param> private void InitiateTransition(TaskShell at) { log.Info("Initiating transition {0}", at.TaskId); TransferDataToTransition(at); at.InitiateTask(); }
/// <summary> /// Extract output data from finished transition by executing task output data bindings /// </summary> /// <param name="at"></param> private void TransferDataFromTransition(TaskShell at) { at.ReceiveOutputDataFromTask(GetProcessVariablesContainer()); ValidateProcessInternalData(); }
/// <summary> /// Execute immediate transition /// </summary> /// <param name="at"></param> private void ExecuteTransition(TaskShell at) { Debug.Assert(at.IsImmediate); TransferDataToTransition(at); foreach (string tokId in at.Tokens) { Token tok1 = GetToken(tokId); tok1.Status = TokenStatus.LOCKED_ENABLED; } at.ExecuteTask(); //not needed (because of transition callback) //OnTransitionCompleted(at.CorrelationId); }
/// <summary> /// Return a list of transitions sharing some tokens with specified transition /// </summary> /// <param name="at"></param> /// <returns></returns> private IList<TaskShell> GetSharedActiveTransitionsForTransition(TaskShell at) { IDictionary<string, TaskShell> dict = new Dictionary<string, TaskShell>(); foreach (string tokid in at.Tokens) { Token t = GetToken(tokid); foreach (string atid in t.ActiveTransitions) { if (dict.ContainsKey(atid)) continue; TaskShell at2 = GetActiveTransition(atid); if (at2 == at) continue; if (at2.Status == TransitionStatus.ENABLED) { dict[atid] = at2; } } } return new List<TaskShell>(dict.Values); }
/// <summary> /// Cancel active transition instance /// How do we do that? /// 1. Do activity-specific cancellation /// 2. Update status of each input token: if it has no more enabled transitions, put it into READY state. Otherwise, leave it in WAITING_TASK /// </summary> /// <param name="at"></param> private void CancelActiveTransition(TaskShell at) { log.Info("Cancelling transition {0}", at.CorrelationId); if (at.IsImmediate) throw new Exception("Cannot cancel an immediate transition"); if (at.Status != TransitionStatus.ENABLED && at.Status != TransitionStatus.STARTED) throw new Exception("Invalid transition status"); at.CancelTask(); Debug.Assert(at.Status == TransitionStatus.CANCELLED); foreach (string t in at.Tokens) { Token tok = GetToken(t); Debug.Assert(tok.Status == TokenStatus.LOCKED_ENABLED || tok.Status == TokenStatus.LOCKED_ALLOCATED); Debug.Assert(tok.ActiveTransitions.Contains(at.CorrelationId)); if (!tok.ActiveTransitions.Remove(at.CorrelationId)) throw new Exception("Error removing transition id from token"); //should never happen if (tok.ActiveTransitions.Count == 0) { tok.Status = TokenStatus.READY; } } ActiveTransitionCancelled ac = new ActiveTransitionCancelled(); ac.CorrelationId = at.CorrelationId; ac.DefinitionId = ProcessDefinitionId; ac.InstanceId = InstanceId; ac.TaskId = at.TaskId; ac.TaskType = Definition.GetTask(at.TaskId).GetType().Name; NotifyProcessEvent(ac); }
/// <summary> /// Add initialized active transition to the collection of active transitions /// Updates transition list for each input token of at. /// </summary> /// <param name="at"></param> private void RegisterNewTransition(TaskShell at) { if (at.CorrelationId == null) throw new Exception("Correlation id required"); if (at.Tokens.Count == 0) throw new Exception("Cannot add a transition without tokens"); Debug.Assert(InstanceId == at.ProcessInstanceId); Debug.Assert(Definition.GetTask(at.TaskId) != null); _activeTransitions[at.CorrelationId] = at; foreach (string tokid in at.Tokens) { Token tok = GetToken(tokid); tok.ActiveTransitions.Add(at.CorrelationId); } }
/// <summary> /// Initiate task /// </summary> /// <param name="at"></param> private void InitiateTransition(TaskShell at) { log.Info("Initiating transition {0}", at.TaskId); Debug.Assert(at.Tokens.Count > 0); foreach (string tokid in at.Tokens) { Token tok = GetToken(tokid); Debug.Assert(tok.Status == TokenStatus.READY || tok.Status == TokenStatus.WAITING || tok.Status == TokenStatus.LOCKED_ENABLED); Debug.Assert(tok.Status != TokenStatus.LOCKED_ENABLED || at.Tokens.Count == 1); } at.InitiateTask(GetProcessDataSource()); }
private TaskShell CreateActiveTransitionForTask(Task tsk) { if (tsk.IsMultiInstance) { MultiTaskShell mts = new MultiTaskShell(this, tsk.Id); mts.CorrelationId = GetNextTransitionId(); mts.SetProcessInstance(this); mts.ParentCallback = this; return mts; } else { TaskShell ts = new TaskShell(this, tsk.Id); ts.CorrelationId = GetNextTransitionId(); ts.SetProcessInstance(this); ts.ParentCallback = this; return ts; } }
public static TaskShell RestoreTaskShell(DataObject state) { string tname = (string)state["Type"]; TaskShell ts; if (tname == "MultiTaskShell") { ts = new MultiTaskShell(); } else if (tname == "TaskShell") { ts = new TaskShell(); } else throw new Exception(); ts.RestoreState(state); return ts; }