Skip to content

Commit 4e7fc41

Browse files
committed
Added IO and Validation services
1 parent d281438 commit 4e7fc41

File tree

52 files changed

+2326
-3
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+2326
-3
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
namespace ServerlessWorkflow.Sdk;
2+
3+
/// <summary>
4+
/// Defines extensions for <see cref="EvaluationResults"/>
5+
/// </summary>
6+
public static class EvaluationResultsExtensions
7+
{
8+
9+
/// <summary>
10+
/// Gets the errors that have occured during evaluation
11+
/// </summary>
12+
/// <param name="results">The extended <see cref="EvaluationResults"/></param>
13+
/// <returns>A new <see cref="IEnumerable{T}"/> containing key/value mapping of the errors that have occured during evaluation</returns>
14+
public static IEnumerable<KeyValuePair<string, string>> GetErrors(this EvaluationResults results)
15+
{
16+
return results.Details.Where(d => !d.IsValid && d.Errors?.Any() == true).Select(e => new KeyValuePair<string, string>(e.EvaluationPath.ToString(), string.Join(Environment.NewLine, e.Errors!.Select(kvp => kvp.Value))));
17+
}
18+
19+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using FluentValidation;
2+
using Microsoft.Extensions.DependencyInjection;
3+
using ServerlessWorkflow.Sdk.Services.FluentBuilders;
4+
using ServerlessWorkflow.Sdk.Services.IO;
5+
using ServerlessWorkflow.Sdk.Services.Validation;
6+
7+
namespace ServerlessWorkflow.Sdk;
8+
9+
/// <summary>
10+
/// Defines extensions for <see cref="IServiceCollection"/>s
11+
/// </summary>
12+
public static class IServiceCollectionExtensions
13+
{
14+
15+
/// <summary>
16+
/// Adds and configures Serverless Workflow services (<see cref="Neuroglia.Serialization.ISerializer"/>s, <see cref="IWorkflowReader"/>, <see cref="IWorkflowWriter"/>, ...)
17+
/// </summary>
18+
/// <param name="services">The <see cref="IServiceCollection"/> to configure</param>
19+
/// <returns>The configured <see cref="IServiceCollection"/></returns>
20+
public static IServiceCollection AddServerlessWorkflow(this IServiceCollection services)
21+
{
22+
services.AddHttpClient();
23+
services.AddSingleton<IWorkflowExternalDefinitionResolver, WorkflowExternalDefinitionResolver>();
24+
services.AddSingleton<IWorkflowReader, WorkflowReader>();
25+
services.AddSingleton<IWorkflowWriter, WorkflowWriter>();
26+
services.AddSingleton<IWorkflowSchemaValidator, WorkflowSchemaValidator>();
27+
services.AddSingleton<IWorkflowValidator, WorkflowValidator>();
28+
services.AddTransient<IWorkflowBuilder, WorkflowBuilder>();
29+
services.AddValidatorsFromAssemblyContaining<WorkflowDefinitionValidator>(ServiceLifetime.Singleton);
30+
return services;
31+
}
32+
33+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
using ServerlessWorkflow.Sdk.Models;
2+
using ServerlessWorkflow.Sdk.Services.IO;
3+
using System;
4+
using System.IO;
5+
using System.Text;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
9+
namespace ServerlessWorkflow.Sdk
10+
{
11+
12+
/// <summary>
13+
/// Defines extensions for <see cref="IWorkflowReader"/>s
14+
/// </summary>
15+
public static class IWorkflowReaderExtensions
16+
{
17+
18+
/// <summary>
19+
/// Reads a <see cref="WorkflowDefinition"/> from the specified <see cref="Stream"/>
20+
/// </summary>
21+
/// <param name="reader">The extended <see cref="IWorkflowReader"/></param>
22+
/// <param name="stream">The <see cref="Stream"/> to read the <see cref="WorkflowDefinition"/> from</param>
23+
/// <param name="cancellationToken">A <see cref="CancellationToken"/></param>
24+
/// <returns>A new <see cref="WorkflowDefinition"/></returns>
25+
public static async Task<WorkflowDefinition> ReadAsync(this IWorkflowReader reader, Stream stream, CancellationToken cancellationToken = default)
26+
{
27+
return await reader.ReadAsync(stream, new(), cancellationToken);
28+
}
29+
30+
/// <summary>
31+
/// Parses the specified input into a new <see cref="WorkflowDefinition"/>
32+
/// </summary>
33+
/// <param name="reader">The extended <see cref="IWorkflowReader"/></param>
34+
/// <param name="input">The input to parse</param>
35+
/// <param name="options"><see cref="WorkflowReaderOptions"/> to use</param>
36+
/// <param name="cancellationToken">A <see cref="CancellationToken"/></param>
37+
/// <returns>A new <see cref="WorkflowDefinition"/></returns>
38+
public static async Task<WorkflowDefinition> ParseAsync(this IWorkflowReader reader, string input, WorkflowReaderOptions options, CancellationToken cancellationToken = default)
39+
{
40+
if (string.IsNullOrWhiteSpace(input))
41+
throw new ArgumentNullException(nameof(input));
42+
using Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(input));
43+
return await reader.ReadAsync(stream, options, cancellationToken);
44+
}
45+
46+
/// <summary>
47+
/// Parses the specified input into a new <see cref="WorkflowDefinition"/>
48+
/// </summary>
49+
/// <param name="reader">The extended <see cref="IWorkflowReader"/></param>
50+
/// <param name="input">The input to parse</param>
51+
/// <param name="cancellationToken">A <see cref="CancellationToken"/></param>
52+
/// <returns>A new <see cref="WorkflowDefinition"/></returns>
53+
public static async Task<WorkflowDefinition> ParseAsync(this IWorkflowReader reader, string input,CancellationToken cancellationToken = default)
54+
{
55+
return await reader.ParseAsync(input, new(), cancellationToken);
56+
}
57+
58+
}
59+
60+
}

ServerlessWorkflow.Sdk/Extensions/StringExtensions.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,21 @@ public static class StringExtensions
2727
/// <returns>The snake-cased string</returns>
2828
public static string ToSnakeCase(this string input) => YamlDotNet.Serialization.NamingConventions.UnderscoredNamingConvention.Instance.Apply(input);
2929

30+
/// <summary>
31+
/// Determines whether or not the specified input is JSON format
32+
/// </summary>
33+
/// <param name="text">The input to check</param>
34+
/// <returns>A boolean indicating whether or not the specified text is JSON format</returns>
35+
public static bool IsJson(this string text)
36+
{
37+
if (string.IsNullOrWhiteSpace(text)) throw new ArgumentNullException(nameof(text));
38+
var text2 = text.Trim();
39+
if (!text2.StartsWith("[") || !text2.EndsWith("]"))
40+
{
41+
if (text2.StartsWith("{")) return text2.EndsWith("}");
42+
else return false;
43+
}
44+
return true;
45+
}
46+
3047
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
namespace ServerlessWorkflow.Sdk;
2+
3+
/// <summary>
4+
/// Defines extensions for <see cref="WorkflowDefinition"/>s
5+
/// </summary>
6+
public static class WorkflowDefinitionExtensions
7+
{
8+
9+
/// <summary>
10+
/// Gets all the <see cref="ActionDefinition"/>s of the specified type declared in the <see cref="WorkflowDefinition"/>
11+
/// </summary>
12+
/// <param name="workflow">The <see cref="WorkflowDefinition"/> to query</param>
13+
/// <param name="type">The type of <see cref="ActionDefinition"/>s to get. A null value gets all <see cref="ActionDefinition"/>s</param>
14+
/// <returns>A new <see cref="IEnumerable{T}"/> containing the <see cref="ActionDefinition"/>s of the specified type declared in the <see cref="WorkflowDefinition"/></returns>
15+
public static IEnumerable<ActionDefinition> GetActions(this WorkflowDefinition workflow, string? type = null)
16+
{
17+
var actions = workflow.States.SelectMany(s => s switch
18+
{
19+
CallbackStateDefinition callbackState => new ActionDefinition[] { callbackState.Action! },
20+
EventStateDefinition eventState => eventState.OnEvents.SelectMany(t => t.Actions),
21+
ForEachStateDefinition foreachState => foreachState.Actions,
22+
OperationStateDefinition operationState => operationState.Actions,
23+
ParallelStateDefinition parallelState => parallelState.Branches.SelectMany(b => b.Actions),
24+
_ => Array.Empty<ActionDefinition>()
25+
});
26+
if (!string.IsNullOrWhiteSpace(type)) actions = actions.Where(a => a.Type == type);
27+
return actions;
28+
}
29+
30+
/// <summary>
31+
/// Gets all the <see cref="FunctionReference"/>s declared in the <see cref="WorkflowDefinition"/>
32+
/// </summary>
33+
/// <param name="workflow">The <see cref="WorkflowDefinition"/> to query</param>
34+
/// <returns>A new <see cref="IEnumerable{T}"/> containing the <see cref="FunctionReference"/>s declared in the <see cref="WorkflowDefinition"/></returns>
35+
public static IEnumerable<FunctionReference> GetFunctionReferences(this WorkflowDefinition workflow) => workflow.GetActions(ActionType.Function).Select(a => a.Function)!;
36+
37+
/// <summary>
38+
/// Gets all the <see cref="EventReference"/>s declared in the <see cref="WorkflowDefinition"/>
39+
/// </summary>
40+
/// <param name="workflow">The <see cref="WorkflowDefinition"/> to query</param>
41+
/// <returns>A new <see cref="IEnumerable{T}"/> containing the <see cref="EventReference"/>s declared in the <see cref="WorkflowDefinition"/></returns>
42+
public static IEnumerable<EventReference> GetEventReferences(this WorkflowDefinition workflow) => workflow.GetActions(ActionType.Event).Select(a => a.Event)!;
43+
44+
/// <summary>
45+
/// Gets all the <see cref="SubflowReference"/>s declared in the <see cref="WorkflowDefinition"/>
46+
/// </summary>
47+
/// <param name="workflow">The <see cref="WorkflowDefinition"/> to query</param>
48+
/// <returns>A new <see cref="IEnumerable{T}"/> containing the <see cref="SubflowReference"/>s declared in the <see cref="WorkflowDefinition"/></returns>
49+
public static IEnumerable<SubflowReference> GetSubflowReferences(this WorkflowDefinition workflow) => workflow.GetActions(ActionType.Subflow).Select(a => a.Subflow)!;
50+
51+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
namespace ServerlessWorkflow.Sdk.Models;
2+
3+
/// <summary>
4+
/// Represents a <see cref="List{T}"/> that can be loaded from an external definition file
5+
/// </summary>
6+
/// <typeparam name="T">The type of elements contained by the <see cref="ExternalDefinitionCollection{T}"/></typeparam>
7+
public class ExternalDefinitionCollection<T>
8+
: List<T>
9+
{
10+
11+
/// <summary>
12+
/// Initializes a new <see cref="ExternalDefinitionCollection{T}"/>
13+
/// </summary>
14+
public ExternalDefinitionCollection()
15+
: base()
16+
{
17+
this.DefinitionUri = null!;
18+
this.Loaded = true;
19+
}
20+
21+
/// <summary>
22+
/// Initializes a new <see cref="ExternalDefinitionCollection{T}"/>
23+
/// </summary>
24+
/// <param name="collection">The collection whose elements are copied into the <see cref="ExternalDefinitionCollection{T}"/></param>
25+
public ExternalDefinitionCollection(IEnumerable<T> collection)
26+
: base(collection)
27+
{
28+
this.DefinitionUri = null!;
29+
this.Loaded = true;
30+
}
31+
32+
/// <summary>
33+
/// Initializes a new <see cref="ExternalDefinitionCollection{T}"/>
34+
/// </summary>
35+
/// <param name="definitionUri">The <see cref="Uri"/> used to reference the file that defines the elements contained by the <see cref="ExternalDefinitionCollection{T}"/></param>
36+
public ExternalDefinitionCollection(Uri definitionUri)
37+
: base()
38+
{
39+
this.DefinitionUri = definitionUri;
40+
this.Loaded = false;
41+
}
42+
43+
/// <summary>
44+
/// Gets the <see cref="Uri"/> used to reference the file that defines the elements contained by the <see cref="ExternalDefinitionCollection{T}"/>
45+
/// </summary>
46+
public virtual Uri DefinitionUri { get; private set; }
47+
48+
/// <summary>
49+
/// Gets a boolean indicating whether or not the <see cref="ExternalDefinitionCollection{T}"/> has been loaded
50+
/// </summary>
51+
public virtual bool Loaded { get; }
52+
53+
}

0 commit comments

Comments
 (0)