Example #1
0
        public TargetState Do(DoOperationInfo info)
        {
            Assert.IsNotNull(info);

            TargetState result = null;
            var chanel = CreateChannel();
            chanel.Call(p =>
            {
                result = p.Do(info);
            });

            return result;
        }
Example #2
0
        public bool Cancel(DoOperationInfo info)
        {
            Assert.IsNotNull(info);

            bool result = false;
            var chanel = CreateChannel();
            chanel.Call(p =>
            {
                result = p.Cancel(info);
            });

            return result;
        }
Example #3
0
 public TargetState Plan(DoOperationInfo info)
 {
     return svr.Plan(info);
 }
Example #4
0
 public TargetState Do(DoOperationInfo info)
 {
     return svr.Do(info);
 }
Example #5
0
 public bool Cancel(DoOperationInfo info)
 {
     return svr.Cancel(info);
 }
        public bool Cancel(DoOperationInfo info)
        {
            var tstate = repoTargetState.Query(o => o.TargetStateId == info.TargetStateId).FirstOrDefault();
            if (tstate == null)
                throw new NullReferenceException(string.Format("Target state {0} not found.", info.TargetStateId));
            var operation = repoFlowOp.Query(o => o.OperationId == info.OperationId).FirstOrDefault();
            if (operation == null)
                throw new NullReferenceException(string.Format("Flow operation {0} not found.", info.OperationId));

            if (operation.CanCancelled == false)
                throw new Exception(string.Format("The operation {0} cannot be cancelled.", operation.Name));

            var state = repoFlowState.Query(o => o.StateId == tstate.StateId).FirstOrDefault();
            if (state == null)
                throw new NullReferenceException(string.Format("Flow state {0} not found.", tstate.StateId));

            if (state.StateType == StateType.Begin && !string.IsNullOrEmpty(tstate.OperatorId) && tstate.OperatorId != info.UserId)
                throw new Exception(string.Format("The state {0} can only be cancelled by the operator {1}.", state.Name, tstate.OperatorName));
            else if (!string.IsNullOrEmpty(tstate.TreaterId) && tstate.TreaterId != info.UserId)
                throw new Exception(string.Format("The state {0} can only be cancelled by the operator {1}.", state.Name, tstate.TreaterName));

            var tflow = repoTargetFlow.Query(o => o.TargetFlowId == tstate.TargetFlowId).First();

            if (tstate.StateStatus == StateStatus.Started)
            {
                try
                {
                    trans.BeginTransaction();
                    tflow.HasStarted = false;
                    repoTargetFlow.Update(tflow);
                    repoTargetIncome.DeleteBatch(o => o.TargetStateId == tstate.TargetStateId);
                    repoTargetOutcome.DeleteBatch(o => o.TargetStateId == tstate.TargetStateId);
                    repoTargetState.Delete(tstate);
                    trans.Commit();
                }
                catch (Exception ex)
                {
                    trans.Rollback();
                    throw ex;
                }
            }
            else
            {
                var lnts = repoNextTargetState.Query(o => o.NextTargetStateId == tstate.TargetStateId).Select(o => o.TargetStateId);
                var lastTStates = repoTargetState.Query(o => lnts.Contains(o.TargetStateId)).Select(o => o.TargetStateId);
                try
                {
                    trans.BeginTransaction();
                    tflow.HasCompleted = false;
                    tflow.Result = null;
                    repoTargetFlow.Update(tflow);
                    repoTargetIncome.DeleteBatch(o => o.TargetStateId == tstate.TargetStateId);
                    repoTargetOutcome.DeleteBatch(o => o.TargetStateId == tstate.TargetStateId);

                    repoTargetState.UpdateBatch(o => lastTStates.Contains(o.TargetStateId), o => new TargetState()
                    {
                        StateStatus = StateStatus.None,
                        TreaterId = null,
                        TreaterName = null,
                        TreatTime = null
                    });

                    repoNextTargetState.DeleteBatch(o => o.NextTargetStateId == tstate.TargetStateId);
                    repoTargetState.Delete(tstate);
                    trans.Commit();
                }
                catch (Exception ex)
                {
                    trans.Rollback();
                    throw ex;
                }
            }
            TargetStateChangedMessage msg = new TargetStateChangedMessage()
            {
                OldTargetStates = new TargetState[] { tstate },
                NewTargetState = null,
                OperationId = null,
                DataOperation = DataOperation.Delete,
                OperateTime = info.OperationTime,
                OperatorId = info.UserId,
                OperatorName = state.StateType == StateType.Begin ? tstate.OperatorName : tstate.TreaterName
            };

            try
            {
                MessageManager.Publish<TargetStateChangedMessage>(msg);
            }
            catch (Exception ex)
            {
                //throw ex;
            }
            return true;
        }
        public TargetState Plan(DoOperationInfo info)
        {
            var tflow = repoTargetFlow.Query(o => o.TargetFlowId == info.TargetFlowId).FirstOrDefault();
            var operation = repoFlowOp.Query(o => o.FlowId == tflow.FlowId && o.OperationId == info.OperationId).FirstOrDefault();
            if (operation == null)
                throw new NullReferenceException(string.Format("Flow operation {0} not found.", info.OperationId));

            if (operation.CanPlanned == false)
                throw new Exception(string.Format("The operation {0} cannot be planned.", operation.Name));

            TargetState tstate = new TargetState()
            {
                TargetStateId = idGenerator.NewId(),
                TargetFlowId = tflow.TargetFlowId,
                StateId = operation.DefaultNextStateId,
                Title = info.Title,
                Message = info.Message,
                StateStatus = StateStatus.Planned,
                PlanTreatTime = info.OperationTime,
                PlannerId = info.UserId,
                PlannerName = info.UserName,
            };

            NextTargetState nts = new NextTargetState()
            {
                TargetStateId = info.TargetStateId,
                NextTargetStateId = tstate.TargetStateId
            };

            try
            {
                trans.BeginTransaction();
                repoTargetState.Insert(tstate);
                repoNextTargetState.Insert(nts);
                trans.Commit();

            }
            catch (Exception ex)
            {
                trans.Rollback();
                throw ex;
            }

            TargetStateChangedMessage msg = new TargetStateChangedMessage()
            {
                OldTargetStates = null,
                NewTargetState = tstate,
                OperationId = null,
                DataOperation = DataOperation.Insert,
                OperateTime = info.OperationTime,
                OperatorId = info.UserId,
                OperatorName = info.UserName
            };
            try
            {
                MessageManager.Publish<TargetStateChangedMessage>(msg);
            }
            catch (Exception ex)
            {
                //throw ex;
            }
            return tstate;
        }
        public TargetState Do(DoOperationInfo info)
        {
            var tflow = repoTargetFlow.Query(o => o.TargetFlowId == info.TargetFlowId).FirstOrDefault();
            if (tflow == null)
                throw new NullReferenceException(string.Format("Target flow {0} not found.", info.TargetFlowId));
            var flow = repoBizFlow.Query(o => o.FlowId == tflow.FlowId).FirstOrDefault();
            if (flow == null)
                throw new NullReferenceException(string.Format("Flow {0} not found.", tflow.FlowId));

            var fop = repoFlowOp.Query(o => o.OperationId == info.OperationId).FirstOrDefault();
            if (fop == null)
                throw new ArgumentNullException(string.Format("Flow operation {0} is not found.", info.OperationId));

                        FlowState nextState = null;
            if (!string.IsNullOrEmpty(info.NextStateIdOrCode))
                nextState = repoFlowState.Query(o => o.FlowId == flow.FlowId && (o.StateId == info.NextStateIdOrCode || o.Code == info.NextStateIdOrCode)).FirstOrDefault();

            if (nextState == null)
                nextState = repoFlowState.Query(o => o.StateId == fop.DefaultNextStateId).FirstOrDefault();
            if (nextState == null)
                throw new NullReferenceException(string.Format("Operation {0} doesn't define next state.", fop.OperationId));

            List<TargetState> needUpdatedTargetStates = new List<TargetState>();
            if(!string.IsNullOrEmpty(info.TargetStateId))
            {
                var tstate = repoTargetState.Query(o => o.TargetStateId == info.TargetStateId).FirstOrDefault();
                needUpdatedTargetStates.Add(tstate);
            }

            // 当前状态为并行结束结点,需要判断当前并行点的所有操作是否都已经完成。
            if (nextState.StateType == StateType.ParallelEnd)
            {
                bool allShouldDone = nextState.AllParallelStateShouldBeEnd.HasValue && nextState.AllParallelStateShouldBeEnd.Value;
                bool canExecute = true;
                var ts = repoTargetState.Query(o => o.TargetFlowId == tflow.TargetFlowId && o.State.StateType == StateType.ParallelStop && (int)o.StateStatus < (int)StateStatus.TreatedNormal).ToArray();
                foreach (var t in ts)
                {
                    var prevStateHasThisOperation = repoStateOp.Query(o => o.StateId == t.StateId && o.OperationId == fop.OperationId).Any();
                    if (allShouldDone)
                        canExecute = canExecute && prevStateHasThisOperation;
                    else
                        canExecute = prevStateHasThisOperation;
                }

                // 必须所有并行的操作都达到下一状态(并行结束ParallelEnd结点),才可以进行后续的操作。
                if (canExecute)
                {
                    // 其他操作中,所有其他操作都已执行且执行后的状态都允许进行后续的操作。即本次操作是并行操作中的最后一个操作。
                    needUpdatedTargetStates.AddRange(ts);
                }
                else
                {
                    throw new InvalidOperationException(string.Format("Target flow {0} is waiting for finishing parallel operations.", info.TargetFlowId));
                }
            }

            List<NextTargetState> nextTargetStates = new List<NextTargetState>();
            string nextTargetStateId = idGenerator.NewId();

            foreach (var tstate in needUpdatedTargetStates)
            {
                var state = repoFlowState.Query(o => o.StateId == tstate.StateId).FirstOrDefault();
                if (state == null)
                    throw new NullReferenceException(string.Format("State {0} not found.", tstate.StateId));

                StateStatus stateStatus = StateStatus.TreatedNormal;
                var sincomes = repoStateIncome.Query(o => o.StateId == tstate.StateId && o.IsRequired == true);
                if (sincomes.Any())
                {
                    var cincomes = repoTargetIncome.Query(o => o.TargetStateId == info.TargetStateId && sincomes.Any(d => d.IncomeId == o.IncomeId) && o.FileStatus != FileStatus.InValid);
                    if (sincomes.Count() > cincomes.Count())
                    {
                        if (flow.StopWhenIncomeRequired)
                        {
                            throw new ApplicationException("Some required incomes are not offered.");
                        }
                        else
                        {
                            stateStatus = StateStatus.TreatedError;
                        }
                    }
                    else
                    {
                        if (cincomes.Any(o => o.FileStatus == FileStatus.Draft))
                            stateStatus = StateStatus.TreatedWarn;
                    }
                }
                var soutcomes = repoStateOutcome.Query(o => o.StateId == tstate.StateId && o.IsRequired == true);
                if (soutcomes.Any())
                {
                    var coutcomes = repoTargetOutcome.Query(o => o.TargetStateId == tstate.TargetStateId && soutcomes.Any(d => d.OutcomeId == o.OutcomeId) && o.FileStatus != FileStatus.InValid);
                    if (soutcomes.Count() > coutcomes.Count())
                    {
                        if (flow.StopWhenIncomeRequired)
                        {
                            throw new ApplicationException("Some required outcomes are not offered.");
                        }
                        else
                        {
                            stateStatus = StateStatus.TreatedError;
                        }
                    }
                    else
                    {
                        if (coutcomes.Any(o => o.FileStatus == FileStatus.Draft))
                            stateStatus = StateStatus.TreatedWarn;
                    }
                }

                tstate.TreatTime = info.OperationTime;
                tstate.StateStatus = stateStatus;
                tstate.TreaterId = info.UserId;
                tstate.TreaterName = info.UserName;

                var nts = repoNextTargetState.Query(o => o.TargetStateId == tstate.TargetStateId && o.ToTargetState.StateId == nextState.StateId).FirstOrDefault();
                if (nts == null)
                {
                    nts = new NextTargetState()
                    {
                        TargetStateId = tstate.TargetStateId,
                        NextTargetStateId = nextTargetStateId
                    };
                }
                else
                {
                    nextTargetStateId = nts.NextTargetStateId;
                }

                if (state.StateType == StateType.ParallelBegin)
                {
                    nts.ParallelTargetStateId = tstate.TargetStateId;
                }
                else if (state.StateType == StateType.ParallelStop || state.StateType == StateType.ParallelEnd)
                {
                    var lastnts = repoNextTargetState.Query(o => o.NextTargetStateId == tstate.TargetStateId).FirstOrDefault();
                    nts.ParallelTargetStateId = lastnts.ParallelTargetStateId;
                }
                nextTargetStates.Add(nts);
            }

            var nextTargetState = repoTargetState.Query(o => nextTargetStateId == o.TargetStateId && o.StateId == nextState.StateId).FirstOrDefault();
            if (nextTargetState == null)
            {
                nextTargetState = new TargetState()
                {
                    TargetStateId = nextTargetStateId,
                    TargetFlowId = tflow.TargetFlowId,
                    StateId = nextState.StateId,
                };
            }

            nextTargetState.Title = info.Title;
            nextTargetState.Message = info.Message;
            nextTargetState.OperateTime = info.OperationTime;
            nextTargetState.StateStatus = StateStatus.None;
            nextTargetState.OperationId = info.OperationId;
            nextTargetState.OperatorId = info.UserId;
            nextTargetState.OperatorName = info.UserName;

            if (nextState.IntervalType.HasValue)
            {
                if (nextState.ResponseIntervalValue.HasValue)
                    nextTargetState.ResponseExpiryTime = info.OperationTime.Interval(nextState.IntervalType, nextState.ResponseIntervalValue);
                if (nextState.TreatIntervalValue.HasValue)
                    nextTargetState.TreatExpiryTime = info.OperationTime.Interval(nextState.IntervalType, nextState.TreatIntervalValue);
            }
            try
            {
                trans.BeginTransaction();
                if (nextState.StateType == StateType.End)
                {
                    nextTargetState.StateStatus = StateStatus.TreatedNormal;
                    tflow.HasCompleted = true;
                    tflow.Result = nextState.Result;
                    repoTargetFlow.Update(tflow);
                }
                needUpdatedTargetStates.ForEach(o => repoTargetState.Update(o));
                repoTargetState.Insert(nextTargetState);
                nextTargetStates.ForEach(o => repoNextTargetState.Save(t => t.TargetStateId == o.TargetStateId && t.NextTargetStateId == o.NextTargetStateId,o));
                trans.Commit();
            }
            catch (Exception ex)
            {
                trans.Rollback();
                throw ex;
            }
            TargetStateChangedMessage msg = new TargetStateChangedMessage()
            {
                OldTargetStates = needUpdatedTargetStates,
                NewTargetState = nextTargetState,
                OperationId = fop.OperationId,
                DataOperation = DataOperation.Update,
                OperateTime = info.OperationTime,
                OperatorId = info.UserId,
                OperatorName = info.UserName
            };

            try
            {
                MessageManager.Publish<TargetStateChangedMessage>(msg);
            }
            catch (Exception ex)
            {
                //throw ex;
            }
            return nextTargetState;
        }