コード例 #1
0
        List <Action> Navigate(IActivity activity, object results, IUser dealer, Context context)
        {
            // 已处理,且状态有变化的才能开始寻找下一步
            if (this.Status != ActivityStates.Dealed || !this.statesChanged || results == null)
            {
                return;
            }
            if (this.Graph.Nexts == null || this.Graph.Nexts.Count == 0)
            {
                return;
            }
            var nextActions  = new List <Action>();
            var nextEntities = new List <ActivityEntity>();
            var navEntities  = new List <NavigationEntity>();

            foreach (var arrow in this.Graph.Nexts)
            {
                // 每条线路只能进入一次
                if (this.Nexts.ContainsKey(arrow.Name))
                {
                    continue;
                }
                var navResults = activity.Navigate(arrow, this, context);
                //检查没通过,不会走该线路
                if (navResults == null)
                {
                    continue;
                }
                // 执行导航
                var nextAction = this.DoNavigate(arrow, navResults, context);


                nextEntities.Add(nextAction.entity);
                nextActions.Add(nextAction);
                navEntities.Add(new NavigationEntity()
                {
                    FromActionId   = this.Id,
                    ToActionId     = nextAction.Id,
                    OwnActionId    = parent.Id,
                    FlowId         = parent.entity.FlowId,
                    NavigationType = arrow.InstanceType,
                    NextDealerId   = navResults.NextDealer?.Id,
                    NextDealerName = navResults.NextDealer?.Name,
                    NextInputs     = JSON.Stringify(navResults.NextInputs),
                    CreateTime     = DateTime.Now,
                    CreatorId      = context.Dealer.Id,
                    CreatorName    = context.Dealer.Name
                });

                this.AddNexts(arrow.Name, nextAction.entity.Id);
            }
            if (nextEntities.Count > 0)
            {
                this.Engine.FlowRepository.Inserts(nextEntities);
                this.Engine.FlowRepository.InsertNavigations(navEntities);
            }
            this.SaveChanges();
            return(nextActions);
        }
コード例 #2
0
        static void ImportStates(Activity activity, object inputs, Context context)
        {
            var node = activity.Graph;

            activity.Entity.Inputs = JSON.Stringify(inputs);
            if (node.Imports != null && node.Imports.Count > 0 && context.Inputs != null)
            {
                var inputDic = JSON.ToDict(inputs);
                if (inputDic != null && inputDic.Count > 0)
                {
                    var states = new Dictionary <string, string>();
                    foreach (var pair in node.Imports)
                    {
                        inputDic.TryGetValue(pair.Key, out string stat);
                        states.Add(pair.Value, stat);
                    }
                    activity.Entity.States = JSON.Stringify(states);
                }
            }
        }
コード例 #3
0
        NavigationEntity CreateNavigation(Activity toActivity, IAssociation assoc, NavigateResults navResults, ProcessContext processContext)
        {
            var entity = new NavigationEntity()
            {
                FromActivityId   = this.FromActivity.Id,
                ToActivityId     = toActivity.Id,
                ParentActivityId = this.FromActivity.ParentId.Value,
                FlowId           = toActivity.FlowId,
                NavigatorType    = assoc.InstanceType,
                NextDealerId     = navResults.NextDealer?.Id,
                NextDealerName   = navResults.NextDealer?.Name,
                NextInputs       = JSON.Stringify(navResults.NextInputs),
                CreateTime       = DateTime.Now,
                CreatorId        = processContext.Dealer.Id,
                CreatorName      = processContext.Dealer.Name
            };

            this.NavigationEntities.Add(entity);
            this.FromActivity.AddNexts(assoc.Name, toActivity.Id);
            return(entity);
        }
コード例 #4
0
        static Activity CreateActivityInstance(Node node, string version, IUser creator, Engine engine)
        {
            Guid id = Guid.NewGuid();

            var entity = new ActivityEntity()
            {
                Id           = id,
                NodeName     = node.Name,
                Status       = ActivityStates.Initializing,
                Version      = version,
                Domain       = engine.Name,
                InstanceType = node.InstanceType ?? engine.DefaultActivityInstanceType,
                Graph        = JSON.Stringify(node),
                HasChildren  = node.Nodes != null && node.Nodes.Count > 0,
                CreateTime   = DateTime.Now,
                CreatorId    = creator.Id,
                CreatorName  = creator.Name
            };

            return(CreateActivityInstance(entity, engine));
        }
コード例 #5
0
        public Activity(Engine engine, Activity parent, INode node, string version, object inputs, IUser creator, IUser owner, ProcessContext processContext)
        {
            this.Engine = engine;
            this.graph  = node;
            this.parent = parent;


            #region init entity
            var entity = new ActivityEntity()
            {
                Id          = Guid.NewGuid(),
                NodeName    = node.Name,
                NodePath    = parent == null ? node.Name : parent.NodePath + "/" + node.Name,
                Status      = ActivityStates.Creating,
                Version     = version ?? parent?.Version,
                Domain      = engine.Name,
                ActionType  = node.InstanceType ?? engine.DefaultActionType,
                Graph       = JSON.Stringify(node),
                HasChildren = node.Nodes != null && node.Nodes.Count > 0,
                Inputs      = JSON.Stringify(inputs),
                CreateTime  = DateTime.Now,
                CreatorId   = creator.Id,
                CreatorName = creator.Name
            };

            this.entity = entity;
            this.Owner  = owner;
            #endregion

            if (parent != null)
            {
                this.FlowRepository = parent.FlowRepository;
                this.AddChild(this);
            }
            else
            {
                this.FlowRepository = engine.ResolveFlowRepository(processContext);
            }

            #region init states
            var states = new JObject();
            var metas  = (node as Node).Metas;
            if (metas != null)
            {
                foreach (var pair in metas)
                {
                    states.Add(pair.Key, pair.Value.DeepClone());
                }
            }
            if (parent != null && node.Imports != null)
            {
                var pStates = parent.States as JObject;
                foreach (var pair in node.Imports)
                {
                    var value = JSON.GetPathValue(pStates, pair.Value);
                    JSON.SetPathValue(states, pair.Key, value);
                }
            }

            this.entity.States = states.ToString();
            this.states        = states;
            #endregion
        }
コード例 #6
0
        private void StartChildActivity(Context context)
        {
            string[] starts = this.Graph.Starts;
            if (starts == null || starts.Length == 0)
            {
                if (this.Graph.Start != null)
                {
                    starts = new string[] { this.Graph.Start }
                }
                ;
            }
            if (starts == null || starts.Length == 0)
            {
                throw new InvalidGraphException("活动{0}配置了nodes,却没有配置start/starts", this.ToString());
            }
            var nextActivities = new List <Activity>();
            var nextEntities   = new List <ActivityEntity>();

            foreach (var startName in starts)
            {
                var startNode = this.Graph.Nodes.FirstOrDefault(p => p.Name == startName);
                if (startNode == null)
                {
                    throw new InvalidGraphException("活动{0}无法找到起始节点{1}", this.ToString(), startName);
                }
                var startActivity = CreateActivityInstance(startNode, this.Dealer, this);
                this.children.Add(startActivity);
                nextEntities.Add(startActivity.Entity);
                nextActivities.Add(startActivity);
            }
            this.Engine.FlowRepository.Inserts(nextEntities, context.Transaction);
            this.DelayExecute((context) => {
                foreach (var nextActivity in nextActivities)
                {
                    nextActivity.Process(context);
                }
            });
        }

        #endregion



        void Done(object executeResults, ITransaction trans, Context context)
        {
            //没有返回任何结果 ,不做进一步尝试
            if (executeResults == null)
            {
                return;
            }

            var changedStates = JObject.FromObject(executeResults);

            foreach (var pair in changedStates)
            {
                if (this.states == null)
                {
                    if (!string.IsNullOrWhiteSpace(this.Entity.States))
                    {
                        this.states = JObject.Parse(this.Entity.States);
                    }
                }
                if (this.states == null)
                {
                    this.states = new JObject();
                }
                this.states[pair.Key] = pair.Value;
                this.statesChanged    = true;
            }

            // 状态转换后,找到下一步的连线
            var navs = this.ResolveNexts(context);

            if (navs == null)
            {
                // 图中就没有下一步
                this.DoneTime = DateTime.Now;
                this.ExportStates(trans);
                // 指示后面执行
                return(new List <NextInfo>());
            }
            else if (navs.Count == 0)
            {
                // 当前状态不足以找到nexts,
                // 节点处于中间状态
                // 返回null,指示deal函数,不做StepToNexts操作
                return(null);
            }
            else
            {
                this.DoneTime = DateTime.Now;
                this.ExportStates(trans);
                return(navs);
            }
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="context"></param>
        /// <returns>null 表示图中没有下一步</returns>
        IList <NextInfo> ResolveNexts(Context context)
        {
            // 该Activity是一个顶层的Flow,没有下一步
            if (this.Parent == null)
            {
                return(null);
            }
            var pNode = this.Flow.Graph;

            if (pNode.Associations == null || pNode.Associations.Count == 0)
            {
                return(null);
            }
            var assocsFromMe = pNode.Associations.Where(p => p.From == this.Name);

            // 没有找到下一步,不执行stepToNexts
            if (assocsFromMe.Count() == 0)
            {
                return(null);
            }
            var nexts = new List <NextInfo>();

            foreach (var assoc in assocsFromMe)
            {
                var nav       = CreateNavigationInstance(assoc.InstanceType);
                var navResult = nav.Navigate(this.states, context);
                if (navResult != null)
                {
                    var toNode = pNode.Nodes.FirstOrDefault(p => p.Name == assoc.To);
                    if (toNode == null)
                    {
                        throw new InvalidGraphException("节点{0}寻找{1}关联的To节点{2}失败,未找到该节点", this.NodePath, nav.Association.Name, nav.Association.To);
                    }
                    nexts.Add(new NextInfo(nav, toNode, navResult));
                }
            }
            return(nexts);
        }

        void ExportStates(ITransaction trans)
        {
            var p = this.Flow;

            if (p == null || this.Graph.Exports == null)
            {
                return;
            }
            foreach (var pair in this.Graph.Exports)
            {
                string value = this[pair.Value];
                p[pair.Key] = value;
            }
            p.SaveChanges(trans);
        }

        void StepToNexts(IList <NextInfo> nextInfos, Context context)
        {
            if (nextInfos.Count > 0)
            {
                List <ActivityEntity> nextEntities = new List <ActivityEntity>();
                foreach (var nextInfo in nextInfos)
                {
                    var nextActivity = CreateActivityInstance(nextInfo);

                    nextInfo.NextActivity = nextActivity;
                    nextEntities.Add(nextActivity.Entity);
                }
                this.Engine.FlowRepository.Inserts(nextEntities, context.Transaction);

                this.DelayExecute((context) => {
                    foreach (var nextInfo in nextInfos)
                    {
                        nextInfo.NextActivity.Process(context);
                    }
                });
                this.Status = ActivityStates.Completed;
            }
            else
            {
                // 没有下一步了
                if (this.Flow != null)
                {
                    this.DelayExecute((context) => {
                        this.Flow.Process(context);
                    });
                }
            }
        }

        void SaveChanges(ITransaction trans)
        {
            if (this.statesChanged)
            {
                this.Entity.States = JSON.Stringify(this.States);
                if (this.statusChanged)
                {
                    if (this.Results != null)
                    {
                        this.Entity.Results = JSON.Stringify(this.Results);
                        this.Engine.FlowRepository.SaveResults(this.Entity, trans);
                    }
                    else
                    {
                        this.Engine.FlowRepository.SaveStatusAndStates(this.Entity, trans);
                    }
                }
                else
                {
                    this.Engine.FlowRepository.SaveStates(this.Entity, trans);
                }
            }
            else
            {
                if (this.statusChanged)
                {
                    if (this.results != null)
                    {
                        this.Entity.Results = JSON.Stringify(this.results);
                        this.Engine.FlowRepository.SaveStatusAndResults(this.Entity, trans);
                    }
                    else
                    {
                        this.Engine.FlowRepository.SaveStatus(this.Entity, trans);
                    }
                }
            }
        }

        Queue <Action <Context> > nextTicks;

        void DelayExecute(Action <Context> handler)
        {
            if (this.nextTicks == null)
            {
                this.nextTicks = new Queue <Action <Context> >();
            }
            this.nextTicks.Enqueue(handler);
        }

        void DelayExecute(Context context)
        {
            if (this.nextTicks == null)
            {
                return;
            }
            Action <Context> handler = this.nextTicks.Dequeue();

            while (this.nextTicks.Count > 0)
            {
                handler(context);

                handler = this.nextTicks.Dequeue();
            }
        }
コード例 #7
0
        public Action(Engine engine, Action parent, Node node, string version, object inputs, IUser creator, IUser dealer = null)
        {
            this.Engine = engine;
            this.graph  = node;
            this.parent = parent;

            #region init entity
            var entity = new ActivityEntity()
            {
                Id           = Guid.NewGuid(),
                NodeName     = node.Name,
                NodePath     = parent == null?node.Name:parent.NodePath + "/" + node.Name,
                Status       = ActivityStates.Created,
                Version      = version ?? parent?.Version,
                Domain       = engine.Name,
                ActivityType = node.InstanceType ?? engine.DefaultActivityInstanceType,
                Graph        = JSON.Stringify(node),
                HasChildren  = node.Nodes != null && node.Nodes.Count > 0,
                Inputs       = JSON.Stringify(inputs),
                CreateTime   = DateTime.Now,
                CreatorId    = creator.Id,
                CreatorName  = creator.Name
            };

            this.entity = entity;
            if (dealer != null)
            {
                this.dealer       = dealer;
                entity.DealerId   = dealer.Id;
                entity.DealerName = dealer.Name;
            }
            #endregion
            #region init states
            var states = new JObject();
            if (node.Meta != null)
            {
                foreach (var pair in node.Meta)
                {
                    states.Add(pair.Key, pair.Value.DeepClone());
                }
            }
            if (parent != null && node.Imports != null)
            {
                var pStates = parent.States as JObject;
                foreach (var pair in node.Imports)
                {
                    var value = JSON.GetPathValue(pStates, pair.Value);
                    JSON.SetPathValue(states, pair.Key, value);
                }
            }
            if (inputs != null)
            {
                var inputObj = JObject.FromObject(inputs);
                foreach (var pair in inputObj)
                {
                    states[pair.Key] = pair.Value;
                }
            }
            this.entity.States = states.ToString();
            this.states        = states;
            #endregion
        }