示例#1
0
        private static HashSet <WorkflowConnectionEntity> GetAllConnections(WorkflowNodeGraph gr, IWorkflowNodeEntity from, IWorkflowNodeEntity to)
        {
            HashSet <WorkflowConnectionEntity> result = new HashSet <WorkflowConnectionEntity>();

            Stack <WorkflowConnectionEntity> partialPath = new Stack <WorkflowConnectionEntity>();
            HashSet <IWorkflowNodeEntity>    visited     = new HashSet <IWorkflowNodeEntity>();
            Action <IWorkflowNodeEntity>     flood       = null;

            flood = node =>
            {
                if (node.Is(to))
                {
                    result.AddRange(partialPath);
                }

                if (node is WorkflowActivityEntity && !node.Is(from))
                {
                    return;
                }


                foreach (var kvp in gr.NextGraph.RelatedTo(node).ToList())
                {
                    if (!visited.Contains(kvp.Key))
                    {
                        visited.Add(kvp.Key);
                        partialPath.Push(kvp.Value);
                        flood(kvp.Key);
                        partialPath.Pop();
                        visited.Remove(kvp.Key);
                    }
                }

                if (node is WorkflowGatewayEntity g && g.Type == WorkflowGatewayType.Inclusive && g.Direction == WorkflowGatewayDirection.Split)
                {
                    var next = gr.ParallelWorkflowPairs.GetOrThrow(g);
                    if (!visited.Contains(next))
                    {
                        visited.Add(next);
                        flood(next);
                        visited.Remove(next);
                    }
                }
            };

            flood(from);

            return(result);
        }
示例#2
0
        public static void Start(SchemaBuilder sb, Func <WorkflowConfigurationEmbedded> getConfiguration)
        {
            if (sb.NotDefined(MethodInfo.GetCurrentMethod()))
            {
                PermissionAuthLogic.RegisterPermissions(WorkflowPermission.ViewWorkflowPanel);
                PermissionAuthLogic.RegisterPermissions(WorkflowPermission.ViewCaseFlow);

                WorkflowLogic.getConfiguration = getConfiguration;

                sb.Include <WorkflowEntity>()
                .WithQuery(() => DynamicQueryCore.Auto(
                               from e in Database.Query <WorkflowEntity>()
                               select new
                {
                    Entity = e,
                    e.Id,
                    e.Name,
                    e.MainEntityType,
                    HasExpired = e.HasExpired(),
                    e.ExpirationDate,
                })
                           .ColumnDisplayName(a => a.HasExpired, () => WorkflowMessage.HasExpired.NiceToString()))
                .WithExpressionFrom((CaseActivityEntity ca) => ca.Workflow());

                WorkflowGraph.Register();
                QueryLogic.Expressions.Register((WorkflowEntity wf) => wf.WorkflowStartEvent());
                QueryLogic.Expressions.Register((WorkflowEntity wf) => wf.HasExpired(), () => WorkflowMessage.HasExpired.NiceToString());
                sb.AddIndex((WorkflowEntity wf) => wf.ExpirationDate);

                DynamicCode.GetCustomErrors += GetCustomErrors;


                sb.Include <WorkflowPoolEntity>()
                .WithUniqueIndex(wp => new { wp.Workflow, wp.Name })
                .WithSave(WorkflowPoolOperation.Save)
                .WithDelete(WorkflowPoolOperation.Delete)
                .WithExpressionFrom((WorkflowEntity p) => p.WorkflowPools())
                .WithQuery(() => e => new
                {
                    Entity = e,
                    e.Id,
                    e.Name,
                    e.BpmnElementId,
                    e.Workflow,
                });

                sb.Include <WorkflowLaneEntity>()
                .WithUniqueIndex(wp => new { wp.Pool, wp.Name })
                .WithSave(WorkflowLaneOperation.Save)
                .WithDelete(WorkflowLaneOperation.Delete)
                .WithExpressionFrom((WorkflowPoolEntity p) => p.WorkflowLanes())
                .WithQuery(() => e => new
                {
                    Entity = e,
                    e.Id,
                    e.Name,
                    e.BpmnElementId,
                    e.Pool,
                    e.Pool.Workflow,
                });

                sb.Include <WorkflowActivityEntity>()
                .WithUniqueIndex(w => new { w.Lane, w.Name })
                .WithSave(WorkflowActivityOperation.Save)
                .WithDelete(WorkflowActivityOperation.Delete)
                .WithExpressionFrom((WorkflowEntity p) => p.WorkflowActivities())
                .WithExpressionFrom((WorkflowLaneEntity p) => p.WorkflowActivities())
                .WithVirtualMList(wa => wa.BoundaryTimers, e => e.BoundaryOf, WorkflowEventOperation.Save, WorkflowEventOperation.Delete)
                .WithQuery(() => e => new
                {
                    Entity = e,
                    e.Id,
                    e.Name,
                    e.BpmnElementId,
                    e.Comments,
                    e.Lane,
                    e.Lane.Pool.Workflow,
                });

                sb.Include <WorkflowEventEntity>()
                .WithExpressionFrom((WorkflowEntity p) => p.WorkflowEvents())
                .WithExpressionFrom((WorkflowLaneEntity p) => p.WorkflowEvents())
                .WithQuery(() => e => new
                {
                    Entity = e,
                    e.Id,
                    e.Type,
                    e.Name,
                    e.BpmnElementId,
                    e.Lane,
                    e.Lane.Pool.Workflow,
                });


                new Graph <WorkflowEventEntity> .Execute(WorkflowEventOperation.Save)
                {
                    CanBeNew      = true,
                    CanBeModified = true,
                    Execute       = (e, _) => {
                        if (e.Timer == null && e.Type.IsTimer())
                        {
                            throw new InvalidOperationException(ValidationMessage._0IsMandatoryWhen1IsSetTo2.NiceToString(e.NicePropertyName(a => a.Timer), e.NicePropertyName(a => a.Type), e.Type.NiceToString()));
                        }

                        if (e.Timer != null && !e.Type.IsTimer())
                        {
                            throw new InvalidOperationException(ValidationMessage._0ShouldBeNullWhen1IsSetTo2.NiceToString(e.NicePropertyName(a => a.Timer), e.NicePropertyName(a => a.Type), e.Type.NiceToString()));
                        }

                        if (e.BoundaryOf == null && e.Type.IsBoundaryTimer())
                        {
                            throw new InvalidOperationException(ValidationMessage._0IsMandatoryWhen1IsSetTo2.NiceToString(e.NicePropertyName(a => a.BoundaryOf), e.NicePropertyName(a => a.Type), e.Type.NiceToString()));
                        }

                        if (e.BoundaryOf != null && !e.Type.IsBoundaryTimer())
                        {
                            throw new InvalidOperationException(ValidationMessage._0ShouldBeNullWhen1IsSetTo2.NiceToString(e.NicePropertyName(a => a.BoundaryOf), e.NicePropertyName(a => a.Type), e.Type.NiceToString()));
                        }

                        e.Save();
                    },
                }

                .Register();

                new Graph <WorkflowEventEntity> .Delete(WorkflowEventOperation.Delete)
                {
                    Delete = (e, _) =>
                    {
                        if (e.Type.IsScheduledStart())
                        {
                            var scheduled = e.ScheduledTask();
                            if (scheduled != null)
                            {
                                WorkflowEventTaskLogic.DeleteWorkflowEventScheduledTask(scheduled);
                            }
                        }

                        e.Delete();
                    },
                }

                .Register();

                sb.Include <WorkflowGatewayEntity>()
                .WithSave(WorkflowGatewayOperation.Save)
                .WithDelete(WorkflowGatewayOperation.Delete)
                .WithExpressionFrom((WorkflowEntity p) => p.WorkflowGateways())
                .WithExpressionFrom((WorkflowLaneEntity p) => p.WorkflowGateways())
                .WithQuery(() => e => new
                {
                    Entity = e,
                    e.Id,
                    e.Type,
                    e.Name,
                    e.BpmnElementId,
                    e.Lane,
                    e.Lane.Pool.Workflow,
                });

                sb.Include <WorkflowConnectionEntity>()
                .WithSave(WorkflowConnectionOperation.Save)
                .WithDelete(WorkflowConnectionOperation.Delete)
                .WithExpressionFrom((WorkflowEntity p) => p.WorkflowConnections())
                .WithExpressionFrom((WorkflowEntity p) => p.WorkflowMessageConnections(), null !)
                .WithExpressionFrom((WorkflowPoolEntity p) => p.WorkflowConnections())
                .WithExpressionFrom((IWorkflowNodeEntity p) => p.NextConnections(), null !)
                .WithExpressionFrom((IWorkflowNodeEntity p) => p.PreviousConnections(), null !)
                .WithQuery(() => e => new
                {
                    Entity = e,
                    e.Id,
                    e.Name,
                    e.BpmnElementId,
                    e.From,
                    e.To,
                });

                WorkflowEventTaskEntity.GetWorkflowEntity = lite => WorkflowGraphLazy.Value.GetOrThrow(lite).Workflow;

                WorkflowGraphLazy = sb.GlobalLazy(() =>
                {
                    using (new EntityCache())
                    {
                        var events      = Database.RetrieveAll <WorkflowEventEntity>().GroupToDictionary(a => a.Lane.Pool.Workflow.ToLite());
                        var gateways    = Database.RetrieveAll <WorkflowGatewayEntity>().GroupToDictionary(a => a.Lane.Pool.Workflow.ToLite());
                        var activities  = Database.RetrieveAll <WorkflowActivityEntity>().GroupToDictionary(a => a.Lane.Pool.Workflow.ToLite());
                        var connections = Database.RetrieveAll <WorkflowConnectionEntity>().GroupToDictionary(a => a.From.Lane.Pool.Workflow.ToLite());

                        var result = Database.RetrieveAll <WorkflowEntity>().ToDictionary(workflow => workflow.ToLite(), workflow =>
                        {
                            var w         = workflow.ToLite();
                            var nodeGraph = new WorkflowNodeGraph
                            {
                                Workflow    = workflow,
                                Events      = events.TryGetC(w).EmptyIfNull().ToDictionary(e => e.ToLite()),
                                Gateways    = gateways.TryGetC(w).EmptyIfNull().ToDictionary(g => g.ToLite()),
                                Activities  = activities.TryGetC(w).EmptyIfNull().ToDictionary(a => a.ToLite()),
                                Connections = connections.TryGetC(w).EmptyIfNull().ToDictionary(c => c.ToLite()),
                            };

                            nodeGraph.FillGraphs();
                            return(nodeGraph);
                        });

                        return(result);
                    }
                }, new InvalidateWith(typeof(WorkflowConnectionEntity)));
                WorkflowGraphLazy.OnReset += (e, args) => DynamicCode.OnInvalidated?.Invoke();

                Validator.PropertyValidator((WorkflowConnectionEntity c) => c.Condition).StaticPropertyValidation = (e, pi) =>
                {
                    if (e.Condition != null && e.From != null)
                    {
                        var conditionType = Conditions.Value.GetOrThrow(e.Condition).MainEntityType;
                        var workflowType  = e.From.Lane.Pool.Workflow.MainEntityType;

                        if (!conditionType.Is(workflowType))
                        {
                            return(WorkflowMessage.Condition0IsDefinedFor1Not2.NiceToString(conditionType, workflowType));
                        }
                    }

                    return(null);
                };

                StartWorkflowConditions(sb);

                StartWorkflowTimerConditions(sb);

                StartWorkflowActions(sb);

                StartWorkflowScript(sb);
            }
        }
示例#3
0
        private static WorkflowEventEntity GetStartEvent(CaseEntity @case, Lite <CaseActivityEntity> firstActivity, WorkflowNodeGraph gr)
        {
            var wet = Database.Query <OperationLogEntity>()
                      .Where(l => l.Operation == CaseActivityOperation.CreateCaseFromWorkflowEventTask.Symbol && l.Target.RefersTo(@case))
                      .Select(l => new { l.Origin, l.User })
                      .SingleOrDefaultEx();

            if (wet != null)
            {
                var lite = (wet.Origin as Lite <WorkflowEventTaskEntity>).InDB(a => a.Event);
                return(lite == null ? null : gr.Events.GetOrThrow(lite));
            }

            bool register = Database.Query <OperationLogEntity>()
                            .Where(l => l.Operation == CaseActivityOperation.Register.Symbol && l.Target.Is(firstActivity) && l.Exception == null)
                            .Any();

            if (register)
            {
                return(gr.Events.Values.SingleEx(a => a.Type == WorkflowEventType.Start));
            }

            return(gr.Events.Values.Where(a => a.Type.IsStart()).Only());
        }
示例#4
0
        public static void Start(SchemaBuilder sb, DynamicQueryManager dqm, Func <WorkflowConfigurationEmbedded> getConfiguration)
        {
            if (sb.NotDefined(MethodInfo.GetCurrentMethod()))
            {
                PermissionAuthLogic.RegisterPermissions(WorkflowScriptRunnerPanelPermission.ViewWorkflowScriptRunnerPanel);

                WorkflowLogic.getConfiguration = getConfiguration;

                sb.Include <WorkflowEntity>()
                .WithQuery(dqm, () => e => new
                {
                    Entity = e,
                    e.Id,
                    e.Name,
                    e.MainEntityType,
                    e.MainEntityStrategy,
                });

                WorkflowGraph.Register();
                dqm.RegisterExpression((WorkflowEntity wf) => wf.WorkflowStartEvent());

                DynamicCode.GetCustomErrors += GetCustomErrors;


                sb.Include <WorkflowPoolEntity>()
                .WithUniqueIndex(wp => new { wp.Workflow, wp.Name })
                .WithSave(WorkflowPoolOperation.Save)
                .WithDelete(WorkflowPoolOperation.Delete)
                .WithExpressionFrom(dqm, (WorkflowEntity p) => p.WorkflowPools())
                .WithQuery(dqm, () => e => new
                {
                    Entity = e,
                    e.Id,
                    e.Name,
                    e.BpmnElementId,
                    e.Workflow,
                });

                sb.Include <WorkflowLaneEntity>()
                .WithUniqueIndex(wp => new { wp.Pool, wp.Name })
                .WithSave(WorkflowLaneOperation.Save)
                .WithDelete(WorkflowLaneOperation.Delete)
                .WithExpressionFrom(dqm, (WorkflowPoolEntity p) => p.WorkflowLanes())
                .WithQuery(dqm, () => e => new
                {
                    Entity = e,
                    e.Id,
                    e.Name,
                    e.BpmnElementId,
                    e.Pool,
                    e.Pool.Workflow,
                });

                sb.Include <WorkflowActivityEntity>()
                .WithUniqueIndex(w => new { w.Lane, w.Name })
                .WithSave(WorkflowActivityOperation.Save)
                .WithDelete(WorkflowActivityOperation.Delete)
                .WithExpressionFrom(dqm, (WorkflowEntity p) => p.WorkflowActivities())
                .WithExpressionFrom(dqm, (WorkflowLaneEntity p) => p.WorkflowActivities())
                .WithQuery(dqm, () => e => new
                {
                    Entity = e,
                    e.Id,
                    e.Name,
                    e.BpmnElementId,
                    e.Comments,
                    e.Lane,
                    e.Lane.Pool.Workflow,
                });

                sb.AddUniqueIndexMList((WorkflowActivityEntity a) => a.Jumps, mle => new { mle.Parent, mle.Element.To });

                sb.Include <WorkflowEventEntity>()
                .WithSave(WorkflowEventOperation.Save)
                .WithExpressionFrom(dqm, (WorkflowEntity p) => p.WorkflowEvents())
                .WithExpressionFrom(dqm, (WorkflowLaneEntity p) => p.WorkflowEvents())
                .WithQuery(dqm, () => e => new
                {
                    Entity = e,
                    e.Id,
                    e.Type,
                    e.Name,
                    e.BpmnElementId,
                    e.Lane,
                    e.Lane.Pool.Workflow,
                });

                new Graph <WorkflowEventEntity> .Delete(WorkflowEventOperation.Delete)
                {
                    Delete = (e, _) =>
                    {
                        if (e.Type.IsTimerStart())
                        {
                            var scheduled = e.ScheduledTask();
                            if (scheduled != null)
                            {
                                WorkflowEventTaskLogic.DeleteWorkflowEventScheduledTask(scheduled);
                            }
                        }

                        e.Delete();
                    },
                }

                .Register();

                sb.Include <WorkflowGatewayEntity>()
                .WithSave(WorkflowGatewayOperation.Save)
                .WithDelete(WorkflowGatewayOperation.Delete)
                .WithExpressionFrom(dqm, (WorkflowEntity p) => p.WorkflowGateways())
                .WithExpressionFrom(dqm, (WorkflowLaneEntity p) => p.WorkflowGateways())
                .WithQuery(dqm, () => e => new
                {
                    Entity = e,
                    e.Id,
                    e.Type,
                    e.Name,
                    e.BpmnElementId,
                    e.Lane,
                    e.Lane.Pool.Workflow,
                });

                sb.Include <WorkflowConnectionEntity>()
                .WithSave(WorkflowConnectionOperation.Save)
                .WithDelete(WorkflowConnectionOperation.Delete)
                .WithExpressionFrom(dqm, (WorkflowEntity p) => p.WorkflowConnections())
                .WithExpressionFrom(dqm, (WorkflowEntity p) => p.WorkflowMessageConnections(), null)
                .WithExpressionFrom(dqm, (WorkflowPoolEntity p) => p.WorkflowConnections())
                .WithExpressionFrom(dqm, (IWorkflowNodeEntity p) => p.NextConnections(), null)
                .WithExpressionFrom(dqm, (IWorkflowNodeEntity p) => p.PreviousConnections(), null)
                .WithQuery(dqm, () => e => new
                {
                    Entity = e,
                    e.Id,
                    e.Name,
                    e.BpmnElementId,
                    e.From,
                    e.To,
                });

                WorkflowGraphLazy = sb.GlobalLazy(() =>
                {
                    using (new EntityCache())
                    {
                        var events      = Database.RetrieveAll <WorkflowEventEntity>().GroupToDictionary(a => a.Lane.Pool.Workflow.ToLite());
                        var gateways    = Database.RetrieveAll <WorkflowGatewayEntity>().GroupToDictionary(a => a.Lane.Pool.Workflow.ToLite());
                        var activities  = Database.RetrieveAll <WorkflowActivityEntity>().GroupToDictionary(a => a.Lane.Pool.Workflow.ToLite());
                        var connections = Database.RetrieveAll <WorkflowConnectionEntity>().GroupToDictionary(a => a.From.Lane.Pool.Workflow.ToLite());

                        var result = Database.RetrieveAll <WorkflowEntity>().ToDictionary(workflow => workflow.ToLite(), workflow =>
                        {
                            var w         = workflow.ToLite();
                            var nodeGraph = new WorkflowNodeGraph
                            {
                                Workflow    = workflow,
                                Events      = events.TryGetC(w).EmptyIfNull().ToDictionary(e => e.ToLite()),
                                Gateways    = gateways.TryGetC(w).EmptyIfNull().ToDictionary(g => g.ToLite()),
                                Activities  = activities.TryGetC(w).EmptyIfNull().ToDictionary(a => a.ToLite()),
                                Connections = connections.TryGetC(w).EmptyIfNull().ToDictionary(c => c.ToLite()),
                            };

                            nodeGraph.FillGraphs();
                            return(nodeGraph);
                        });

                        return(result);
                    }
                }, new InvalidateWith(typeof(WorkflowConnectionEntity)));

                Validator.PropertyValidator((WorkflowConnectionEntity c) => c.Condition).StaticPropertyValidation = (e, pi) =>
                {
                    if (e.Condition != null && e.From != null)
                    {
                        var conditionType = Conditions.Value.GetOrThrow(e.Condition).MainEntityType;
                        var workflowType  = e.From.Lane.Pool.Workflow.MainEntityType;

                        if (!conditionType.Is(workflowType))
                        {
                            return(WorkflowMessage.Condition0IsDefinedFor1Not2.NiceToString(conditionType, workflowType));
                        }
                    }

                    return(null);
                };

                sb.Include <WorkflowConditionEntity>()
                .WithSave(WorkflowConditionOperation.Save)
                .WithQuery(dqm, () => e => new
                {
                    Entity = e,
                    e.Id,
                    e.Name,
                    e.MainEntityType,
                    e.Eval.Script
                });

                new Graph <WorkflowConditionEntity> .Delete(WorkflowConditionOperation.Delete)
                {
                    Delete = (e, _) =>
                    {
                        ThrowConnectionError(Database.Query <WorkflowConnectionEntity>().Where(a => a.Condition == e.ToLite()), e);
                        e.Delete();
                    },
                }

                .Register();

                new Graph <WorkflowConditionEntity> .ConstructFrom <WorkflowConditionEntity>(WorkflowConditionOperation.Clone)
                {
                    Construct = (e, args) =>
                    {
                        return(new WorkflowConditionEntity
                        {
                            MainEntityType = e.MainEntityType,
                            Eval = new WorkflowConditionEval {
                                Script = e.Eval.Script
                            }
                        });
                    },
                }

                .Register();

                WorkflowEventTaskEntity.GetWorkflowEntity = lite => WorkflowGraphLazy.Value.GetOrThrow(lite).Workflow;

                Conditions = sb.GlobalLazy(() => Database.Query <WorkflowConditionEntity>().ToDictionary(a => a.ToLite()),
                                           new InvalidateWith(typeof(WorkflowConditionEntity)));

                sb.Include <WorkflowActionEntity>()
                .WithSave(WorkflowActionOperation.Save)
                .WithQuery(dqm, () => e => new
                {
                    Entity = e,
                    e.Id,
                    e.Name,
                    e.MainEntityType,
                    e.Eval.Script
                });

                new Graph <WorkflowActionEntity> .Delete(WorkflowActionOperation.Delete)
                {
                    Delete = (e, _) =>
                    {
                        ThrowConnectionError(Database.Query <WorkflowConnectionEntity>().Where(a => a.Action == e.ToLite()), e);
                        e.Delete();
                    },
                }

                .Register();

                new Graph <WorkflowActionEntity> .ConstructFrom <WorkflowActionEntity>(WorkflowActionOperation.Clone)
                {
                    Construct = (e, args) =>
                    {
                        return(new WorkflowActionEntity
                        {
                            MainEntityType = e.MainEntityType,
                            Eval = new WorkflowActionEval {
                                Script = e.Eval.Script
                            }
                        });
                    },
                }

                .Register();

                Actions = sb.GlobalLazy(() => Database.Query <WorkflowActionEntity>().ToDictionary(a => a.ToLite()),
                                        new InvalidateWith(typeof(WorkflowActionEntity)));

                sb.Include <WorkflowScriptEntity>()
                .WithSave(WorkflowScriptOperation.Save)
                .WithQuery(dqm, () => s => new
                {
                    Entity = s,
                    s.Id,
                    s.Name,
                    s.MainEntityType,
                });

                new Graph <WorkflowScriptEntity> .Delete(WorkflowScriptOperation.Delete)
                {
                    Delete = (s, _) =>
                    {
                        ThrowConnectionError(Database.Query <WorkflowActivityEntity>().Where(a => a.Script.Script == s.ToLite()), s);
                        s.Delete();
                    },
                }

                .Register();

                Scripts = sb.GlobalLazy(() => Database.Query <WorkflowScriptEntity>().ToDictionary(a => a.ToLite()),
                                        new InvalidateWith(typeof(WorkflowScriptEntity)));

                sb.Include <WorkflowScriptRetryStrategyEntity>()
                .WithSave(WorkflowScriptRetryStrategyOperation.Save)
                .WithDelete(WorkflowScriptRetryStrategyOperation.Delete)
                .WithQuery(dqm, () => e => new
                {
                    Entity = e,
                    e.Id,
                    e.Rule
                });
            }
        }