Beispiel #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="engine"></param>
        /// <param name="WorkflowFilePath"></param>
        /// <param name="XsdPath"></param>
        /// <returns></returns>
        public Workflow CheckAndLoadWorkflow(CWFEngine engine, string WorkflowFilePath, string XsdPath)
        {
            _workflowMemento = new WorkflowMemento();

            _workflowMemento.WorkflowFilePath = WorkflowFilePath;
            _XsdPath = XsdPath;

            Check();
            var wf = Load(engine);

            foreach (var activity in wf.Activities)
            {
                activity.Finished += wf.Activity_Finished;
            }
            return(wf);
        }
Beispiel #2
0
 public Workflow(CWFEngine cwfEngine, Parser.WorkflowMemento memento)
 {
     Description                      = memento.Description;
     Id                               = memento.Id;
     IsEnabled                        = memento.IsEnabled;
     LaunchType                       = memento.LaunchType;
     Name                             = memento.Name;
     Period                           = memento.Period;
     StateToken                       = memento.StateToken as INotifyPropertyChanged;
     WorkflowFilePath                 = memento.WorkflowFilePath;
     XmlNamespaceManager              = memento.XmlNamespaceManager;
     StateToken.PropertyChanged      += StateToken_PropertyChanged;
     Engine                           = cwfEngine;
     _runningActivities               = new ConcurrentDictionary <int, Task>();
     _incomingTransitionsOfActivities = new ConcurrentDictionary <int, List <int> >();
     _cancelationToken                = CancellationSource.Token;
 }
Beispiel #3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="engine"></param>
        /// <returns></returns>
        Workflow Load(CWFEngine engine)
        {
            using (var xmlReader = XmlReader.Create(_workflowMemento.WorkflowFilePath))
            {
                var xmlNameTable = xmlReader.NameTable;
                if (xmlNameTable != null)
                {
                    _workflowMemento.XmlNamespaceManager = new XmlNamespaceManager(xmlNameTable);
                    _workflowMemento.XmlNamespaceManager.AddNamespace("wf", "urn:cwf-schema");
                }
                else
                {
                    throw new Exception("xmlNameTable of " + _workflowMemento.WorkflowFilePath + " is null");
                }

                // Loading settings
                var       xdoc = XDocument.Load(_workflowMemento.WorkflowFilePath);
                XDocument XDoc = xdoc;
                XNamespaceWf = "urn:cwf-schema";

                _workflowMemento.Id          = int.Parse(GetWorkflowAttribute(xdoc, "id"));
                _workflowMemento.Name        = GetWorkflowAttribute(xdoc, "name");
                _workflowMemento.Description = GetWorkflowAttribute(xdoc, "description");

                _workflowMemento.LaunchType = (LaunchType)Enum.Parse(typeof(LaunchType), GetWorkflowSetting(xdoc, "launchType"), true);
                if (_workflowMemento.LaunchType == LaunchType.Periodic)
                {
                    _workflowMemento.Period = TimeSpan.Parse(GetWorkflowSetting(xdoc, "period"));
                }
                _workflowMemento.IsEnabled = bool.Parse(GetWorkflowSetting(xdoc, "enabled"));

                //create state token
                try
                {
                    var typename = GetWorkflowSetting(xdoc, "statemachinetype");
                    _workflowMemento.StateToken = CreateStateToken(typename);
                    InitializeTransitionDefinitionBuilder(xdoc);

                    Logger.Info($"Instantiated State token");
                }
                catch (FileNotFoundException fnfe)
                {
                    Logger.Error($"A required library was not found: {fnfe.FileName}");
                }
                catch (Exception e)
                {
                    Logger.Error($"Exception on creating state machine token: {e.ToString()}");
                    return(null);
                }

                if (xdoc.Root != null)
                {
                    var xExecutionGraph = xdoc.Root.Element(XNamespaceWf + Sym.ACTIVITY_SETUP);
                    IsExecutionGraphEmpty = xExecutionGraph == null || !xExecutionGraph.Elements().Any();
                }
                var wf = new Workflow(engine, _workflowMemento);
                // Loading tasks
                var activities = new List <Activity>();
                foreach (var xTaskElement in xdoc.XPathSelectElements("/wf:Workflow/wf:Activities/wf:Activity", _workflowMemento.XmlNamespaceManager))
                {
                    var xAttribute = xTaskElement.Attribute("name");
                    if (xAttribute != null)
                    {
                        var name = xAttribute.Value;

                        ActivityMemento activityMemento = ParseActivity(xTaskElement, wf);
                        Activity        activity        = LoadActivityInstance(name, activityMemento);

                        activities.Add(activity);
                    }
                    else
                    {
                        throw new Exception("Name attribute of the task " + xTaskElement + " does not exist.");
                    }
                }

                wf.Activities = activities.ToArray();

                //read all transition definitions
                var transitionList = new List <Transition>();
                foreach (var xTaskElement in xdoc.XPathSelectElements("/wf:Workflow/wf:Transitions/wf:Transition", _workflowMemento.XmlNamespaceManager))
                {
                    var xAttributeId        = xTaskElement.Attribute("id");
                    var xAttributeFrom      = xTaskElement.Attribute("from");
                    var xAttributeTo        = xTaskElement.Attribute("to");
                    var xAttributeCondition = xTaskElement.Attribute("condition");

                    int    id          = int.Parse(xAttributeId.Value);
                    int    from        = int.Parse(xAttributeFrom.Value);
                    int    to          = int.Parse(xAttributeTo.Value);
                    string condition   = xAttributeCondition?.Value;
                    var    genericType = typeof(Transition <>).MakeGenericType(_stateType);
                    var    transition  = (Transition)Activator.CreateInstance(genericType, new object[] { id, from, to, condition });
                    OnTransitionDefinitionInXml(transition);
                    transitionList.Add(transition);
                    Logger.Info(transition.ToString());
                }
                wf.Transitions = transitionList.ToArray();
                var d = CompileAndGetMethodInfos();
                LinkTransitionsToCompiledConditions(wf.Transitions, d);

                // Loading execution graph
                var xExectionGraph = xdoc.XPathSelectElement("/wf:Workflow/wf:ActivitySetup", _workflowMemento.XmlNamespaceManager);
                if (xExectionGraph != null)
                {
                    var taskNodes = GetTaskNodes(xExectionGraph);

                    // Check startup node, parallel tasks and infinite loops
                    if (taskNodes.Any())
                    {
                        if (CheckStartupNode(taskNodes) == false)
                        {
                            Logger.Trace("Startup node with parentId=-1 not found in ExecutionGraph execution graph.");
                            throw new Exception();
                        }
                    }

                    if (CheckParallelTasks(taskNodes))
                    {
                        Logger.Trace("Parallel tasks execution detected in ExecutionGraph execution graph.");
                    }

                    CheckInfiniteLoop(taskNodes, "Infinite loop detected in ExecutionGraph execution graph.");

                    // OnSuccess
                    GraphEvent onSuccess  = null;
                    var        xOnSuccess = xExectionGraph.XPathSelectElement("wf:OnSuccess", _workflowMemento.XmlNamespaceManager);
                    if (xOnSuccess != null)
                    {
                        var onSuccessNodes = GetTaskNodes(xOnSuccess);

                        if (CheckStartupNode(onSuccessNodes) == false)
                        {
                            Logger.Trace("Startup node with parentId=-1 not found in OnSuccess execution graph.");
                            throw new Exception();
                        }

                        if (CheckParallelTasks(onSuccessNodes))
                        {
                            Logger.Trace("Parallel tasks execution detected in OnSuccess execution graph.");
                        }

                        CheckInfiniteLoop(onSuccessNodes, "Infinite loop detected in OnSuccess execution graph.");
                        onSuccess = new GraphEvent(onSuccessNodes);
                    }

                    // OnWarning
                    GraphEvent onWarning  = null;
                    var        xOnWarning = xExectionGraph.XPathSelectElement("wf:OnWarning", _workflowMemento.XmlNamespaceManager);
                    if (xOnWarning != null)
                    {
                        var onWarningNodes = GetTaskNodes(xOnWarning);

                        if (CheckStartupNode(onWarningNodes) == false)
                        {
                            Logger.Trace("Startup node with parentId=-1 not found in OnWarning execution graph.");
                            throw new Exception();
                        }

                        if (CheckParallelTasks(onWarningNodes))
                        {
                            Logger.Trace("Parallel tasks execution detected in OnSuccess execution graph.");
                        }

                        CheckInfiniteLoop(onWarningNodes, "Infinite loop detected in OnWarning execution graph.");
                        onWarning = new GraphEvent(onWarningNodes);
                    }

                    // OnError
                    GraphEvent onError  = null;
                    var        xOnError = xExectionGraph.XPathSelectElement("wf:OnError", _workflowMemento.XmlNamespaceManager);
                    if (xOnError != null)
                    {
                        var onErrorNodes = GetTaskNodes(xOnError);

                        if (CheckStartupNode(onErrorNodes) == false)
                        {
                            Logger.Trace("Startup node with parentId=-1 not found in OnError execution graph.");
                            return(null);
                        }

                        if (CheckParallelTasks(onErrorNodes))
                        {
                            Logger.Trace("Parallel tasks execution detected in OnError execution graph.");
                        }

                        CheckInfiniteLoop(onErrorNodes, "Infinite loop detected in OnError execution graph.");
                        onError = new GraphEvent(onErrorNodes);
                    }

                    wf.ActivitySetup = new Graph(taskNodes, onSuccess, onWarning, onError);
                }
                return(wf);
            }
        }