/objectflow.core/Framework/Workflow.cs
C# | 303 lines | 169 code | 43 blank | 91 comment | 7 complexity | 228511745c8fc6c00602cd84e076bd4d MD5 | raw file
- using System;
- using Rainbow.Exceptions;
- using Rainbow.ObjectFlow.Engine;
- using Rainbow.ObjectFlow.Interfaces;
- using Rainbow.ObjectFlow.Language;
- using Rainbow.ObjectFlow.Policies;
- using System.Linq;
-
- namespace Rainbow.ObjectFlow.Framework
- {
- /// <summary>
- /// Pipelines are composed of generic IOperations. A pipeline
- /// controls the workflow whereas the IOperation encapsalates logic.
- /// </summary>
- public class Workflow<T> : IWorkflow<T>, IDefine<T>, ICompose<T>, IMerge<T>, IExecuteWorkflow<T> where T : class
- {
- private WorkflowBuilder<T> _workflowBuilder;
- private readonly Dispatcher<T> _workflowEngine;
- private TaskList<T> _tasklist;
- private AndOperand<T> _andOperand;
- /// <summary>
- /// default constructor
- /// </summary>
- public Workflow()
- {
- _workflowEngine = new Dispatcher<T>();
- _workflowBuilder = new SequentialBuilder<T>();
- _tasklist = new TaskList<T>();
- _workflowBuilder.OperationAdded += _tasklist.OperationAdded;
- ExceptionHandler = new ExceptionHandler();
- }
-
- internal Workflow(WorkflowBuilder<T> builder)
- {
- _workflowBuilder = builder;
- }
-
- internal Workflow(Dispatcher<T> workflowEngine, TaskList<T> tasklist)
- : this()
- {
- _workflowEngine = workflowEngine;
- _tasklist = tasklist;
- _workflowBuilder.OperationAdded += _tasklist.OperationAdded;
- }
-
- /// <summary>
- /// Joins one operation onto another to run in parallel
- /// <remarks>
- /// Although data will be passed to operations or functions running in parallel
- /// these operations will not affect the data passed to subsequent operations. This was to reduce the
- /// complexity of parallel operations in Version 1.x and this behaviour may be extended to
- /// pass state in the future.
- /// </remarks>
- /// </summary>
- public IAnd<T> And
- {
- get
- {
- if (IsSequentialBuilder(_workflowBuilder))
- {
- var operation = RemoveLastOperation();
- _andOperand = CreateAndInitialiseAndJoin(operation);
- }
-
- return _andOperand;
- }
- }
-
- private AndOperand<T> CreateAndInitialiseAndJoin(OperationDuplex<T> operation)
- {
- _workflowBuilder = new ParallelSplitBuilder<T>();
- _workflowBuilder.OperationAdded += _tasklist.OperationAdded;
- _andOperand = new AndOperand<T>(this, _workflowBuilder);
- _andOperand.Do(operation);
-
- return _andOperand;
- }
-
- private OperationDuplex<T> RemoveLastOperation()
- {
- // TODO: and should probably subscribe to events and raise it to workflow builder. this would decouple the builder from the and.
- var operation = _tasklist.Tasks[_tasklist.Tasks.Count - 1];
- _tasklist.Tasks.RemoveAt(_tasklist.Tasks.Count - 1);
- return operation;
- }
-
- /// <summary>
- /// Gets or sets the context of the workflow.
- /// </summary>
- /// <value>The context for the workflow operations.</value>
- public T Context
- {
- get { return _workflowEngine.Context; }
- set { _workflowEngine.Context = value; }
- }
-
- //TODO remove?
- internal TaskList<T> RegisteredOperations
- {
- get { return _tasklist; }
- }
-
- internal ExceptionHandler ExceptionHandler { get; set; }
-
- /// <summary>
- /// Adds an operation into the workflow definition
- /// </summary>
- /// <param name="operation">The operation to execute as a generic of IOperation</param>
- /// <remarks>Operations must inherit from the BasicOperation class</remarks>
- public virtual IWorkflow<T> Do(IOperation<T> operation)
- {
- Check.IsNotNull(operation, "operation");
- Check.IsInstanceOf<BasicOperation<T>>(operation, "operation");
-
- _workflowBuilder.AddOperation(operation);
-
- return this;
- }
-
- /// <summary>
- /// Adds an operation into the workflow definition given the constraint. The constraint runs if
- /// the constraint evaluates to true.
- /// </summary>
- /// <param name="operation">The operation to execute as a generic of IOperation</param>
- /// <param name="constraint">The constraint to evaluate</param>
- /// <remarks>Operations must inherit from the BasicOperation class</remarks>
- public virtual IWorkflow<T> Do(IOperation<T> operation, ICheckConstraint constraint)
- {
- Check.IsNotNull(operation, "operation");
- Check.IsNotNull(constraint, "constraint");
- Check.IsInstanceOf<BasicOperation<T>>(operation, "operation");
-
- _workflowBuilder.AddOperation(operation, constraint);
-
- return this;
- }
-
- /// <summary>
- /// Adds a function into the workflow definition
- /// </summary>
- /// <param name="function">Function to add</param>
- public IWorkflow<T> Do(Func<T, T> function)
- {
- Check.IsNotNull(function, "function");
-
- _workflowBuilder.AddOperation(function);
- return this;
- }
-
- /// <summary>
- /// Adds a function into the workflow definition
- /// </summary>
- /// <param name="function">Function to add</param>
- /// <param name="constraint">constraint defines if function will be executed</param>
- public IWorkflow<T> Do(Func<T, T> function, ICheckConstraint constraint)
- {
- Check.IsNotNull(function, "function");
- Check.IsNotNull(constraint, "constraint");
-
- _workflowBuilder.AddOperation(function, constraint);
- return this;
- }
-
- /// <summary>
- /// Begins the execution of a workflow
- /// </summary>
- /// <returns>The data after being transformed by the Operation objects</returns>
- /// <remarks>
- /// This is only valid for state objects where operations on null can be performed as this delegates to Start(T data) by passing it null.
- /// </remarks>
- public virtual T Start()
- {
- return Start(default(T));
- }
-
- /// <summary>
- /// Runs the workflow definition
- /// </summary>
- /// <param name="data">Data to transform</param>
- /// <returns>Result of the workflow</returns>
- public virtual T Start(T data)
- {
- Then();
- ExceptionHandler.When(() => _workflowEngine.Execute(_tasklist.Tasks, data));
- return Context;
- }
-
- /// <summary>
- /// Subsequent Operations and functions will execute after the previous one has completed.
- /// </summary>
- public virtual IMerge<T> Then()
- {
- if (!IsSequentialBuilder(_workflowBuilder))
- {
- _tasklist.Tasks.Add(new OperationDuplex<T>(_workflowBuilder.ParallelOperations));
-
- _workflowBuilder = new SequentialBuilder<T>();
-
- //SetCurrentTasksFromList(_tasklist.Tasks.ToArray());
- _workflowBuilder.OperationAdded += _tasklist.OperationAdded;
- }
-
- return this;
- }
-
- private static bool IsSequentialBuilder(WorkflowBuilder<T> builder)
- {
- return null == builder || (typeof(SequentialBuilder<T>) == builder.GetType());
- }
-
- /// <summary>
- /// Instantiates a workflow object
- /// </summary>
- public static IDefine<T> Definition()
- {
- return new Workflow<T>();
- }
-
- /// <summary>
- /// Adds a sub-workflow into the workflow definition
- /// </summary>
- /// <param name="workflow">Workflow to add</param>
- public IWorkflow<T> Do(IExecuteWorkflow<T> workflow)
- {
- Check.IsNotNull(workflow, "workflow");
- _workflowBuilder.AddOperation(workflow);
-
- return this;
- }
-
- /// <summary>
- /// Adds a sub-workflow into the workflow definition
- /// </summary>
- /// <param name="workflow">Workflow to add</param>
- /// <param name="constraint">pre-condition for execution</param>
- public IWorkflow<T> Do(IExecuteWorkflow<T> workflow, ICheckConstraint constraint)
- {
- Check.IsNotNull(workflow, "workflow");
- Check.IsNotNull(constraint, "constraint");
-
- _workflowBuilder.AddOperation(workflow, constraint);
-
- return this;
- }
-
- /// <summary>
- /// Allows an operation to be attempted again
- /// </summary>
- public IRetryPolicy Retry()
- {
- IRetryPolicy policy = new Retry(this);
- if (_tasklist.Tasks.Count > 0)
- {
- _tasklist.Tasks[_tasklist.Tasks.Count - 1].Command.Policies.Add(policy);
- }
-
- return policy;
- }
-
- /// <summary>
- /// Does the operation again. Unlike Retry, this does not check on success or failure
- /// </summary>
- /// <returns></returns>
- public IRepeat Repeat()
- {
- IRepeat policy = new Repeat(this);
- if (_tasklist.Tasks.Count > 0)
- {
- _tasklist.Tasks[_tasklist.Tasks.Count - 1].Command.Policies.Add(policy);
- }
-
- return policy;
- }
-
- /// <summary>
- /// Registers an instance of the type specified in the workflow
- /// </summary>
- /// <typeparam name="TOperation">Type that inherits from BasicOperation of T</typeparam>
- public IWorkflow<T> Do<TOperation>() where TOperation : BasicOperation<T>
- {
- _workflowBuilder.AddOperation<TOperation>();
-
- return this;
- }
-
- /// <summary>
- /// Registers an instance of the type specified in the workflow
- /// </summary>
- /// <typeparam name="TOperation">Type that inherits from BasicOperation of T</typeparam>
- /// <param name="constraint">The constraint to evaluate</param>
- public IWorkflow<T> Do<TOperation>(ICheckConstraint constraint) where TOperation : BasicOperation<T>
- {
- _workflowBuilder.AddOperation<TOperation>(constraint);
-
- return this;
- }
-
- // public static IHandle Configure()
- // {
- // return new ExceptionHandler();
- // }
- }
- }