Esempio n. 1
0
        /// <exception cref="WorkflowException">A workflow exception occurred. </exception>
        private async Task <WorkflowActivityOutput> CompleteInternalAsync <TInput>(
            IWorkflowActivityBase activity, CancellationToken cancellationToken, TInput input)
            where TInput : WorkflowActivityInput
        {
            if (CurrentActivityIds.Contains(activity.Id))
            {
                input = CreateActivityInput(activity, input);

                WorkflowActivityOutput result;
                try
                {
                    result = await activity.CompleteAsync(input, cancellationToken);
                }
                catch (Exception exception)
                {
                    return(HandleCompletionException(exception));
                }

                if (result.Successful)
                {
                    return(await HandleCompletionSuccess(activity, result));
                }
                else
                {
                    return(HandleCompletionFailed(result));
                }
            }
            throw new WorkflowException("The activity to complete could not be found in the current activity list. ");
        }
Esempio n. 2
0
 /// <exception cref="WorkflowException">A workflow exception occurred. </exception>
 private TInput CreateActivityInput <TInput>(IWorkflowActivityBase activity, TInput input)
     where TInput : WorkflowActivityInput
 {
     input          = input ?? (TInput)Activator.CreateInstance(activity.InputType);
     input.Instance = this;
     foreach (var route in activity.Routes)
     {
         var outputData = Data.FirstOrDefault(d => d.ActivityId == route.OutputActivityId);
         if (outputData != null)
         {
             var inputProperty = input.GetType().GetRuntimeProperty(route.InputProperty);
             if (inputProperty != null)
             {
                 var outputProperty = outputData.Output.GetType().GetRuntimeProperty(route.OutputProperty);
                 if (outputProperty != null)
                 {
                     inputProperty.SetValue(input, outputProperty.GetValue(outputData.Output));
                 }
                 else
                 {
                     throw new WorkflowException("The output property of the route could not be found on the output data. ");
                 }
             }
             else
             {
                 throw new WorkflowException("The input property of the route could not be found on the input data. ");
             }
         }
         else
         {
             throw new WorkflowException("The requested input data for the activity could not be found. ");
         }
     }
     return(input);
 }
        /// <summary>Gets the next activities or null when no condition is available. </summary>
        /// <param name="activity">The current workflow activity. </param>
        /// <param name="definition">The workflow definition. </param>
        /// <returns>The next activities. </returns>
        /// <exception cref="WorkflowException">No next activities could be found based on the given condition. </exception>
        /// <exception cref="WorkflowException">More then one activity found for condition but activity is not a ForkActivity. </exception>
        public IWorkflowActivityBase[] GetNextActivities(IWorkflowActivityBase activity, WorkflowDefinition definition)
        {
            if (string.IsNullOrEmpty(NextActivitiesCondition))
            {
                return(null);
            }

            var nextActivities = definition.GetOutboundTransitions(activity)
                                 .Where(t => t.Condition == NextActivitiesCondition)
                                 .Select(t => definition.GetActivityById(t.To))
                                 .ToArray();

            if (nextActivities.Length == 0)
            {
                throw new WorkflowException(
                          string.Format("No next activities could be found based on the given condition '{0}'. ", NextActivitiesCondition));
            }

            if (nextActivities.Length > 1 && !(activity is ForkActivity))
            {
                throw new WorkflowException(
                          string.Format("More then one activity found for condition '{0}' " +
                                        "but activity is not a ForkActivity. ", NextActivitiesCondition));
            }

            return(nextActivities);
        }
Esempio n. 4
0
 /// <summary>Initializes a new instance of the <see cref="WorkflowRoute"/> class. </summary>
 /// <typeparam name="TOutputActivity">The type of the output activity's output. </typeparam>
 /// <typeparam name="TInputActivity">The type of the input activity's input. </typeparam>
 /// <param name="outputActivity">The output activity. </param>
 /// <param name="outputPropertyExpression">The output property as expression. </param>
 /// <param name="inputPropertyExpression">The output property as expression. </param>
 /// <returns>The <see cref="WorkflowRoute"/>. </returns>
 public static WorkflowRoute Create <TOutputActivity, TInputActivity>(IWorkflowActivityBase outputActivity,
                                                                      Expression <Func <TOutputActivity, object> > outputPropertyExpression,
                                                                      Expression <Func <TInputActivity, object> > inputPropertyExpression)
     where TInputActivity : WorkflowActivityInput
     where TOutputActivity : WorkflowActivityOutput
 {
     return(Create(outputActivity.Id, outputPropertyExpression, inputPropertyExpression));
 }
Esempio n. 5
0
        /// <exception cref="WorkflowException">Default outgoing transitions of cannot be conditional. </exception>
        private IWorkflowActivityBase[] GetDefaultNextActivities(IWorkflowActivityBase activity)
        {
            var transitions = WorkflowDefinition.GetOutboundTransitions(activity).ToArray();

            if (transitions.Any(t => t.IsConditional))
            {
                throw new WorkflowException(string.Format("Default outgoing transitions of ({0}) cannot be conditional. ", activity.Id));
            }

            return(transitions
                   .Select(t => WorkflowDefinition.GetActivityById(t.To))
                   .ToArray());
        }
Esempio n. 6
0
        private void AddActivityResultToData(IWorkflowActivityBase activity, WorkflowActivityOutput result)
        {
            var data = Data.SingleOrDefault(d => d.ActivityId == activity.Id);

            if (data != null)
            {
                Data.Remove(data);
            }

            Data.Add(new ActivityData {
                ActivityId = activity.Id, Output = result
            });
        }
Esempio n. 7
0
 /// <summary>Executes the given activity with the given arguments. </summary>
 /// <exception cref="WorkflowException">A workflow exception occurred. </exception>
 public async Task <WorkflowActivityOutput> CompleteAsync <TInput>(
     IWorkflowActivityBase activity, CancellationToken cancellationToken, TInput input)
     where TInput : WorkflowActivityInput
 {
     try
     {
         IsRunning = true;
         return(await CompleteInternalAsync(activity, cancellationToken, input));
     }
     finally
     {
         IsRunning = false;
         RaiseCurrentActivitiesChanged();
     }
 }
Esempio n. 8
0
        private bool HasCurrentActivityBeforeActivity(WorkflowActivityInput input, WorkflowDefinition definition,
            IWorkflowActivityBase activity, List<WorkflowTransition> checkedTransitions)
        {
            var inboundTransitions = definition.GetInboundTransitions(activity);
            if (inboundTransitions.Any(t => input.Instance.CurrentActivityIds.Contains(t.From)))
                return true;

            checkedTransitions.AddRange(inboundTransitions);
            foreach (var transition in inboundTransitions)
            {
                if (HasCurrentActivityBeforeActivity(input, definition, definition.GetActivityById(transition.From), checkedTransitions))
                    return true;
            }

            return false;
        }
        /// <summary>Gets the next activities or null when no condition is available. </summary>
        /// <param name="activity">The current workflow activity. </param>
        /// <param name="definition">The workflow definition. </param>
        /// <returns>The next activities. </returns>
        /// <exception cref="WorkflowException">No next activities could be found based on the given condition. </exception>
        /// <exception cref="WorkflowException">More then one activity found for condition but activity is not a ForkActivity. </exception>
        public IWorkflowActivityBase[] GetNextActivities(IWorkflowActivityBase activity, WorkflowDefinition definition)
        {
            if (string.IsNullOrEmpty(NextActivitiesCondition))
                return null; 
            
            var nextActivities = definition.GetOutboundTransitions(activity)
                .Where(t => t.Condition == NextActivitiesCondition)
                .Select(t => definition.GetActivityById(t.To))
                .ToArray();

            if (nextActivities.Length == 0)
                throw new WorkflowException(
                    string.Format("No next activities could be found based on the given condition '{0}'. ", NextActivitiesCondition));

            if (nextActivities.Length > 1 && !(activity is ForkActivity))
                throw new WorkflowException(
                    string.Format("More then one activity found for condition '{0}' " +
                                  "but activity is not a ForkActivity. ", NextActivitiesCondition));

            return nextActivities;
        }
Esempio n. 10
0
        private bool HasCurrentActivityBeforeActivity(WorkflowActivityInput input, WorkflowDefinition definition,
                                                      IWorkflowActivityBase activity, List <WorkflowTransition> checkedTransitions)
        {
            var inboundTransitions = definition.GetInboundTransitions(activity);

            if (inboundTransitions.Any(t => input.Instance.CurrentActivityIds.Contains(t.From)))
            {
                return(true);
            }

            checkedTransitions.AddRange(inboundTransitions);
            foreach (var transition in inboundTransitions)
            {
                if (HasCurrentActivityBeforeActivity(input, definition, definition.GetActivityById(transition.From), checkedTransitions))
                {
                    return(true);
                }
            }

            return(false);
        }
Esempio n. 11
0
        /// <exception cref="WorkflowException">A workflow validation exception occurred. </exception>
        private void ValidateRoute(IWorkflowActivityBase inputActivity, WorkflowRoute route)
        {
            var outputActivity = GetActivityById(route.OutputActivityId);
            var outputProperty = outputActivity.OutputType.GetRuntimeProperty(route.OutputProperty);

            if (outputProperty == null)
            {
                throw new WorkflowException("The output property of the route could not be found on the output data type. ");
            }

            var inputProperty = inputActivity.InputType.GetRuntimeProperty(route.InputProperty);

            if (inputProperty == null)
            {
                throw new WorkflowException("The input property of the route could not be found on the input data type. ");
            }

            if (outputProperty.PropertyType != inputProperty.PropertyType)
            {
                throw new WorkflowException("The input property and output property types of a route do not match. ");
            }
        }
Esempio n. 12
0
        /// <exception cref="WorkflowException">A workflow exception occurred. </exception>
        private async Task <WorkflowActivityOutput> HandleCompletionSuccess(IWorkflowActivityBase activity, WorkflowActivityOutput result)
        {
            AddActivityResultToData(activity, result);

            var nextActivities = result.GetNextActivities(activity, WorkflowDefinition);

            if (nextActivities == null)
            {
                nextActivities = GetDefaultNextActivities(activity);
            }

            if (!(activity is ForkActivity) && nextActivities.Length > 1)
            {
                throw new WorkflowException(string.Format("Activity ({0}) has multiple next activities ({1}) " +
                                                          "but only ForkActivity activities can return multiple activities. ",
                                                          activity.Id, string.Join(", ", nextActivities.Select(a => a.Id))));
            }

            CurrentActivityIds.Remove(activity.Id);

            await AddNextActivitiesAsync(activity, nextActivities);

            return(result);
        }
Esempio n. 13
0
        /// <exception cref="WorkflowException">A workflow exception occurred. </exception>
        private async Task AddNextActivitiesAsync(IWorkflowActivityBase activity, IList <IWorkflowActivityBase> nextActivities)
        {
            var allowedTransitions = WorkflowDefinition.GetOutboundTransitions(activity);

            var hasFollowingActivities = allowedTransitions.Length > 0;

            if (!hasFollowingActivities)
            {
                return;
            }

            var areNextActivitiesAllowed = nextActivities.All(a => allowedTransitions.Any(t => t.To == a.Id));

            if (areNextActivitiesAllowed)
            {
                await PrepareNextActivities(nextActivities);
            }
            else
            {
                throw new WorkflowException(
                          string.Format("Transitions for activities ({0}) produced by activity ({1}) could not be found. ",
                                        string.Join(", ", nextActivities.Select(a => a.Id)), activity.Id));
            }
        }
Esempio n. 14
0
 /// <summary>Gets the inbound transitions of a given inputActivity. </summary>
 /// <param name="activity">The inputActivity. </param>
 /// <returns>The transitions. </returns>
 public WorkflowTransition[] GetInboundTransitions(IWorkflowActivityBase activity)
 {
     return(Transitions.Where(t => t.To == activity.Id).ToArray());
 }
Esempio n. 15
0
 /// <summary>Initializes a new instance of the <see cref="WorkflowRoute"/> class. </summary>
 /// <param name="outputActivity">The output activity. </param>
 /// <param name="outputProperty">The output property defined on the output activity's output type. </param>
 /// <param name="inputProperty">The input property defined on the input activity's input type. </param>
 public WorkflowRoute(IWorkflowActivityBase outputActivity, string outputProperty, string inputProperty)
 {
     OutputActivityId = outputActivity.Id;
     OutputProperty   = outputProperty;
     InputProperty    = inputProperty;
 }
Esempio n. 16
0
        /// <exception cref="WorkflowException">A workflow validation exception occurred. </exception>
        private void ValidateRoute(IWorkflowActivityBase inputActivity, WorkflowRoute route)
        {
            var outputActivity = GetActivityById(route.OutputActivityId);
            var outputProperty = outputActivity.OutputType.GetRuntimeProperty(route.OutputProperty);
            if (outputProperty == null)
                throw new WorkflowException("The output property of the route could not be found on the output data type. ");

            var inputProperty = inputActivity.InputType.GetRuntimeProperty(route.InputProperty);
            if (inputProperty == null)
                throw new WorkflowException("The input property of the route could not be found on the input data type. ");

            if (outputProperty.PropertyType != inputProperty.PropertyType)
                throw new WorkflowException("The input property and output property types of a route do not match. ");
        }
Esempio n. 17
0
 /// <summary>Gets the inbound transitions of a given inputActivity. </summary>
 /// <param name="activity">The inputActivity. </param>
 /// <returns>The transitions. </returns>
 public WorkflowTransition[] GetInboundTransitions(IWorkflowActivityBase activity)
 {
     return Transitions.Where(t => t.To == activity.Id).ToArray();
 }
Esempio n. 18
0
 /// <summary>Initializes a new instance of the <see cref="WorkflowTransition"/> class. </summary>
 public WorkflowTransition(IWorkflowActivityBase from, IWorkflowActivityBase to)
 {
     From = from.Id;
     To = to.Id;
 }
Esempio n. 19
0
 /// <summary>Initializes a new instance of the <see cref="WorkflowTransition"/> class. </summary>
 public WorkflowTransition(IWorkflowActivityBase from, IWorkflowActivityBase to)
 {
     From = from.Id;
     To   = to.Id;
 }
Esempio n. 20
0
 /// <summary>Executes the given activity with the given arguments. </summary>
 /// <exception cref="WorkflowException">A workflow exception occurred. </exception>
 public Task <WorkflowActivityOutput> CompleteAsync(IWorkflowActivityBase activity, CancellationToken cancellationToken)
 {
     return(CompleteAsync <WorkflowActivityInput>(activity, cancellationToken, null));
 }
Esempio n. 21
0
 /// <summary>Executes the given activity with the given arguments. </summary>
 /// <exception cref="WorkflowException">A workflow exception occurred. </exception>
 public Task <WorkflowActivityOutput> CompleteAsync <TInput>(IWorkflowActivityBase activity, TInput input)
     where TInput : WorkflowActivityInput
 {
     return(CompleteAsync(activity, CancellationToken.None, input));
 }