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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy