/// <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); }
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; }
/// <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); } }