From dc14436bd908ba7d0474ad267dabcb4f68b4baf3 Mon Sep 17 00:00:00 2001 From: mikolaj-milewski Date: Sat, 15 Jun 2024 00:11:46 +0200 Subject: [PATCH] Feat/tokens reworked (#27) * Initial implementation - anything as a token - anything as initialization (unfinished) - sm standard requests turned to commands (unfinished) * Token -> Object * Restore * Works! * Fixes on token handling - token identity is now taken under consideration and tokens are not duplicated in inputs - non-outputting structured activities are now producing control token * Tokens reworked Everything can be token now! * Little cleanup * 0.12.3-alpha * Multiple changes --- .editorconfig | 10 + .../Activities/Classes/ActivityWrapper.cs | 4 +- .../Activities/Events/ExecutionRequest.cs | 4 +- .../Activities/Events/ExecutionResponse.cs | 2 +- .../Extensions/ExecutionResponseExtensions.cs | 3 +- .../IBehaviorLocatorActivityExtensions.cs | 2 - .../Extensions/TokenInfoExtensions.cs | 20 -- .../Activities/Interfaces/IActivity.cs | 2 +- Core/Stateflows.Common/Events/Event.cs | 6 +- .../Events/TimeEvents/RecurringEvent.cs | 2 - .../Extensions/EventInfoExtensions.cs | 5 +- .../Extensions/PayloadObjectExtensions.cs | 23 +- .../Extensions/TokenInfoExtensions.cs | 10 +- .../Extensions/TypeExtensions.cs | 2 +- .../Stateflows.Common/Interfaces/IBehavior.cs | 7 +- .../Interfaces/IBehaviorLocator.cs | 6 + .../Interfaces/ISubscriptions.cs | 13 + Core/Stateflows.Common/Interfaces/IWatches.cs | 12 + Core/Stateflows.Common/Tokens/GroupToken.cs | 16 - Core/Stateflows.Common/Tokens/Token.cs | 52 --- .../Utilities/BehaviorExtensions.cs | 46 --- .../Utilities/DataBehaviorExtensions.cs | 3 + .../Utilities/StateflowsJsonConverter.cs | 8 +- .../Cradle/Context/ActivityContext.cs | 40 +++ .../Activities/Cradle/Context/NodeContext.cs | 22 ++ .../Cradle/Context/TypedActionContext.cs | 24 ++ .../Activities/Cradle/FlowTestCradle.cs | 40 +++ .../Cradle/FlowTestCradleBuilder.cs | 51 +++ .../Cradle/IFlowTestCradleBuilder.cs | 13 + .../Cradle/INodeTestCradleBuilder.cs | 12 + .../Activities/Cradle/ITestCradle.cs | 9 + .../Activities/Cradle/ITestResults.cs | 11 + .../Activities/Cradle/NodeTestCradle.cs | 38 ++ .../Cradle/NodeTestCradleBuilder.cs | 59 ++++ .../Activities/Cradle/TestResults.cs | 28 ++ .../Stateflows.Testing/StateflowsTestClass.cs | 13 +- .../Stateflows.Common.Transport.csproj | 4 - .../Classes/AcceptEventActionNode.cs | 5 +- .../Activities/Classes/ActionNode.cs | 5 +- .../Activities/Classes/ActivityFinal.cs | 9 - .../Activities/Classes/ActivityNode.cs | 8 +- .../Activities/Classes/ControlDecisionNode.cs | 9 + .../Activities/Classes/DecisionNode.cs | 4 +- .../Stateflows/Activities/Classes/ElseFlow.cs | 26 +- .../Classes/ExceptionHandlerNode.cs | 2 +- Core/Stateflows/Activities/Classes/Flow.cs | 30 +- .../Classes/IterativeActivityNode.cs | 4 +- .../Classes/ParalellActivityNode.cs | 4 +- .../Classes/StructuredActivityNode.cs | 6 +- .../Activities/Classes/TokensAccessor.cs | 20 ++ .../Activities/Collections/Input.cs | 24 +- .../Activities/Collections/Output.cs | 19 +- .../Classes/AcceptEventActionContext.cs | 18 +- .../Context/Classes/ActionContext.cs | 50 +-- .../Classes/ActivityFlowContextAccessor.cs | 10 + .../Context/Classes/ActivityNodeContext.cs | 2 +- .../Classes/ActivityNodeContextAccessor.cs | 10 + .../Context/Classes/EventContext.cs | 4 +- .../Classes/ExceptionHandlerContext.cs | 21 +- .../Activities/Context/Classes/FlowContext.cs | 48 +++ .../Activities/Context/Classes/NodeContext.cs | 20 +- .../Activities/Context/Classes/RootContext.cs | 18 +- .../Context/Classes/SourceNodeContext.cs | 24 +- .../Context/Classes/TokenFlowContext.cs | 18 +- .../Context/Classes/TokenPipelineContext.cs | 9 +- .../Interfaces/IAcceptEventActionContext.cs | 2 +- .../Context/Interfaces/IActionContext.cs | 5 +- .../Interfaces/IActivityActionContext.cs | 3 + .../Context/Interfaces/IActivityContext.cs | 6 + .../Interfaces/IActivityFlowContext.cs | 33 ++ .../Interfaces/IActivityNodeContext.cs | 6 + .../Context/Interfaces/IEventContext.cs | 2 +- .../Interfaces/IExceptionHandlerContext.cs | 2 + .../Context/Interfaces/IFlowContext.cs | 17 - .../Context/Interfaces/IGuardContext.cs | 9 +- .../Activities/Context/Interfaces/IInput.cs | 3 +- .../Context/Interfaces/INodeContext.cs | 25 +- .../Activities/Context/Interfaces/IOutput.cs | 18 +- .../Context/Interfaces/IPipelineContext.cs | 5 +- .../Context/Interfaces/ITokenContext.cs | 4 +- .../Interfaces/ITransformationContext.cs | 5 +- Core/Stateflows/Activities/Engine/Executor.cs | 190 +++++----- .../Stateflows/Activities/Engine/Inspector.cs | 62 ++-- .../Stateflows/Activities/Engine/NodeScope.cs | 68 ++-- .../Activities/Engine/Plugins/AcceptEvents.cs | 65 +--- .../Activities/Engine/Plugins/Tracer.cs | 42 +-- Core/Stateflows/Activities/Engine/Provider.cs | 2 - .../Extensions/BuilderExtensions.cs | 154 +++++++-- .../IEnumerableOfTokensExtensions.cs | 16 - .../Extensions/IOutputExtensions.cs | 23 -- .../IServiceCollectionExtensions.cs | 37 +- .../Activities/Extensions/OutputExtensions.cs | 16 - .../Inspection/Classes/FlowInspection.cs | 4 +- .../Interfaces/IEventInspectionContext.cs | 2 +- .../Interfaces/IGuardInspectionContext.cs | 2 +- .../ITransformationInspectionContext.cs | 2 +- .../Activities/Interfaces/IActivity.cs | 2 +- .../Interfaces/IActivityExceptionHandler.cs | 29 +- .../Interfaces/IActivityInspector.cs | 69 ++-- .../Interfaces/IActivityInterceptor.cs | 16 +- .../Interfaces/IActivityObserver.cs | 53 ++- .../Activities/Interfaces/ITokensAccessor.cs | 10 + .../Stateflows/Activities/Models/Delegates.cs | 9 +- Core/Stateflows/Activities/Models/Edge.cs | 1 + Core/Stateflows/Activities/Models/Graph.cs | 8 +- Core/Stateflows/Activities/Models/Node.cs | 19 +- .../Registration/Builders/ActivityBuilder.cs | 18 + .../Builders/BaseActivityBuilder.cs | 26 +- .../Registration/Builders/DecisionBuilder.cs | 4 +- .../Registration/Builders/FlowBuilder.cs | 24 +- .../Registration/Builders/NodeBuilder.cs | 25 +- .../Builders/StructuredActivityBuilder.cs | 3 - .../Registration/Interfaces/Base/IActivity.cs | 6 +- .../Interfaces/Base/IActivityUtils.cs | 20 ++ .../Interfaces/Base/IObjectFlow.cs | 89 ++++- .../Interfaces/Base/IReactiveActivity.cs | 10 +- .../Registration/Interfaces/Delegates.cs | 16 +- ...ctionBuilderExceptionHandlersExtensions.cs | 12 +- ...tionBuilderObjectFlowsPayloadExtensions.cs | 11 - ...ActionBuilderObjectFlowsTypedExtensions.cs | 38 +- ...uilderObjectFlowsTypedPayloadExtensions.cs | 46 --- ...ctionBuilderExceptionHandlersExtensions.cs | 12 +- ...tionBuilderObjectFlowsPayloadExtensions.cs | 11 - ...ActionBuilderObjectFlowsTypedExtensions.cs | 25 +- ...uilderObjectFlowsTypedPayloadExtensions.cs | 46 --- .../ActivityBuilderAnonymousExtensions.cs | 2 - .../ActivityBuilderSpecialsExtensions.cs | 22 +- ...ctivityBuilderSpecialsPayloadExtensions.cs | 11 - .../ActivityBuilderTypedExtensions.cs | 20 +- .../ActivityBuilderTypedPayloadExtensions.cs | 20 -- .../DataStoreBuilderFlowsPayloadExtensions.cs | 11 - .../DataStoreBuilderFlowsTypedExtensions.cs | 25 +- ...StoreBuilderFlowsTypedPayloadExtensions.cs | 43 --- ...BuilderElseObjectFlowsPayloadExtensions.cs | 11 - ...onBuilderElseObjectFlowsTypedExtensions.cs | 68 ++-- ...erElseObjectFlowsTypedPayloadExtensions.cs | 45 --- ...sionBuilderObjectFlowsPayloadExtensions.cs | 11 - ...cisionBuilderObjectFlowsTypedExtensions.cs | 68 ++-- ...uilderObjectFlowsTypedPayloadExtensions.cs | 45 --- ...InputBuilderControlFlowsTypedExtensions.cs | 3 +- .../InputBuilderFlowsPayloadExtensions.cs | 11 - .../Flows/InputBuilderFlowsTypedExtensions.cs | 16 +- ...InputBuilderFlowsTypedPayloadExtensions.cs | 30 -- .../JoinBuilderFlowsPayloadExtensions.cs | 11 - .../Flows/JoinBuilderFlowsTypedExtensions.cs | 28 +- .../JoinBuilderFlowsTypedPayloadExtensions.cs | 43 --- ...ergeBuilderObjectFlowsPayloadExtensions.cs | 12 - .../MergeBuilderObjectFlowsTypedExtensions.cs | 25 +- ...uilderObjectFlowsTypedPayloadExtensions.cs | 43 --- ...edActivityBuilderFlowsPayloadExtensions.cs | 11 - ...uredActivityBuilderFlowsTypedExtensions.cs | 14 +- ...ivityBuilderFlowsTypedPayloadExtensions.cs | 30 -- ...turedActivityBuilderAnonymousExtensions.cs | 5 +- ...cturedActivityBuilderSpecialsExtensions.cs | 22 +- ...ctivityBuilderSpecialsPayloadExtensions.cs | 11 - ...tructuredActivityBuilderTypedExtensions.cs | 23 +- ...edActivityBuilderTypedPayloadExtensions.cs | 20 -- ...edActivityBuilderFlowsPayloadExtensions.cs | 11 - ...uredActivityBuilderFlowsTypedExtensions.cs | 16 +- ...ivityBuilderFlowsTypedPayloadExtensions.cs | 30 -- ...turedActivityBuilderAnonymousExtensions.cs | 2 - ...cturedActivityBuilderSpecialsExtensions.cs | 24 +- ...ctivityBuilderSpecialsPayloadExtensions.cs | 11 - ...tructuredActivityBuilderTypedExtensions.cs | 20 +- ...edActivityBuilderTypedPayloadExtensions.cs | 20 -- ...ypedActionBuilderFlowsPayloadExtensions.cs | 11 - .../TypedActionBuilderFlowsTypedExtensions.cs | 14 +- ...ctionBuilderFlowsTypedPayloadExtensions.cs | 30 -- .../TypedActivityBuilderSpecialsExtensions.cs | 15 +- ...ctivityBuilderSpecialsPayloadExtensions.cs | 11 - .../TypedActivityBuilderTypedExtensions.cs | 20 +- ...edActivityBuilderTypedPayloadExtensions.cs | 20 -- .../Interfaces/IActivityBuilder.cs | 2 + .../Interfaces/IDecisionBuilder.cs | 2 - .../Registration/Interfaces/IFlowBuilder.cs | 13 +- .../Classes/IntegratedActivityBuilder.cs | 4 +- .../CompositeStateBuilderExtensions.cs | 28 +- .../Extensions/StateBuilderExtensions.cs | 16 +- .../Extensions/TransitionBuilderExtensions.cs | 4 +- .../Activities/Streams/NodeStreams.cs | 56 --- Core/Stateflows/Activities/Streams/Stream.cs | 9 +- Core/Stateflows/Activities/Tokens/Control.cs | 5 + .../Activities/Tokens/ControlToken.cs | 9 - .../Activities/Tokens/EventToken.cs | 10 - .../Activities/Tokens/ExceptionHolder.cs | 36 ++ .../Activities/Tokens/ExceptionToken.cs | 11 - .../Activities/Tokens/NodeReference.cs | 9 + .../Activities/Tokens/TokenHolder.cs | 41 +++ .../Activities/Utils/IEnumerableExtensions.cs | 34 +- .../Activities/Utils/ObjectExtensions.cs | 34 ++ .../Common/Classes/BaseValueAccessor.cs | 42 +++ .../Common/Classes/ContextValues.cs | 19 +- Core/Stateflows/Common/Classes/EventQueue.cs | 5 + .../Common/Classes/GlobalValueAccessors.cs | 10 + .../Common/Classes/ValueAccessors.cs | 22 ++ .../Context/Interfaces/IBehaviorContext.cs | 19 +- Core/Stateflows/GlobalSuppressions.cs | 9 + .../StateMachines/Engine/Executor.cs | 18 +- .../StateMachines/Engine/Plugins/Behaviors.cs | 81 +---- .../Engine/Plugins/ContextCleanup.cs | 75 ---- .../Engine/Plugins/Notifications.cs | 119 +++---- .../Engine/Plugins/TimeEvents.cs | 63 ---- .../StateMachines/Engine/Provider.cs | 2 - .../IStateMachineExceptionHandler.cs | 31 +- .../Interfaces/IStateMachineInterceptor.cs | 15 +- .../Interfaces/IStateMachineObserver.cs | 63 +++- Core/Stateflows/StateMachines/Models/Graph.cs | 16 - .../Registration/Builders/StateBuilder.cs | 37 +- .../Builders/StateMachineBuilder.cs | 45 +++ .../Builders/TransitionBuilder.cs | 19 +- .../Interfaces/Base/IStateMachineUtils.cs | 6 + ...zedCompositeStateBuilderTypedExtensions.cs | 2 - ...lizedStateMachineBuilderTypedExtensions.cs | 2 - ...zedCompositeStateBuilderTypedExtensions.cs | 2 - ...lizedStateMachineBuilderTypedExtensions.cs | 2 - Core/Stateflows/System/Engine/Provider.cs | 2 - .../Blazor.Server/Pages/Activities.razor | 4 +- .../Blazor/Server/Blazor.Server/Program.cs | 89 +++-- .../MassTransit.Service2/Program.cs | 1 + .../ActivityTracer.cs | 114 ++++++ .../DependencyInjection.cs | 17 + .../StateMachineTracer.cs | 90 +++++ .../Stateflows.Extensions.Logging.csproj | 12 + .../Classes/ActivityPlantUmlGenerator.cs | 3 +- .../Stateflows.Locks.DistributedLock.csproj | 4 - Stateflows.sln | 7 +- ...teflows.Storage.EntityFrameworkCore.csproj | 4 - .../Classes/Tokens/SomeToken.cs | 7 + .../Tests/AcceptEvent.cs | 87 +++++ .../Tests/ActionUnit.cs | 75 ++++ .../Tests/Context.cs | 80 +++++ .../Tests/DataStore.cs | 64 ++++ .../Tests/Decision.cs | 100 ++++++ .../Tests/Exceptions.cs | 326 +++++++++++++++++- Tests/Activity.IntegrationTests/Tests/Fork.cs | 56 +++ .../Tests/Initialization.cs | 3 +- .../Tests/Iterative.cs | 61 ++++ Tests/Activity.IntegrationTests/Tests/Join.cs | 62 ++++ .../Activity.IntegrationTests/Tests/Merge.cs | 62 ++++ .../Activity.IntegrationTests/Tests/Output.cs | 20 +- .../Tests/Parallel.cs | 64 ++++ .../Tests/Structured.cs | 134 +++++++ .../Tests/TokenIdentity.cs | 65 ++++ .../Activity.IntegrationTests/Tests/Typed.cs | 84 +++++ .../Activity.IntegrationTests/Tests/Values.cs | 63 ++++ .../Activity.IntegrationTests/Tests/Weight.cs | 76 ++++ .../StateMachines/ValuesStateMachine.cs | 21 ++ .../Classes/States/ValueState1.cs | 21 ++ .../Classes/States/ValueState2.cs | 10 + .../Classes/Transitions/GuardedTransition.cs | 16 + .../Classes/Transitions/InternalTransition.cs | 21 ++ .../Classes/Transitions/ValueTransition.cs | 15 + .../Tests/Composite.cs | 2 +- .../Tests/Context.cs | 69 ++++ .../Tests/Values.cs | 43 +++ Transport/@stateflows/common/package.json | 2 +- .../@stateflows/http-client/package.json | 4 +- .../@stateflows/signalr-client/package.json | 4 +- .../Stateflows.Transport.Http.csproj | 5 - 259 files changed, 4175 insertions(+), 2493 deletions(-) create mode 100644 .editorconfig delete mode 100644 Core/Stateflows.Common/Activities/Extensions/TokenInfoExtensions.cs delete mode 100644 Core/Stateflows.Common/Tokens/GroupToken.cs delete mode 100644 Core/Stateflows.Common/Tokens/Token.cs delete mode 100644 Core/Stateflows.Common/Utilities/BehaviorExtensions.cs create mode 100644 Core/Stateflows.Testing/Activities/Cradle/Context/ActivityContext.cs create mode 100644 Core/Stateflows.Testing/Activities/Cradle/Context/NodeContext.cs create mode 100644 Core/Stateflows.Testing/Activities/Cradle/Context/TypedActionContext.cs create mode 100644 Core/Stateflows.Testing/Activities/Cradle/FlowTestCradle.cs create mode 100644 Core/Stateflows.Testing/Activities/Cradle/FlowTestCradleBuilder.cs create mode 100644 Core/Stateflows.Testing/Activities/Cradle/IFlowTestCradleBuilder.cs create mode 100644 Core/Stateflows.Testing/Activities/Cradle/INodeTestCradleBuilder.cs create mode 100644 Core/Stateflows.Testing/Activities/Cradle/ITestCradle.cs create mode 100644 Core/Stateflows.Testing/Activities/Cradle/ITestResults.cs create mode 100644 Core/Stateflows.Testing/Activities/Cradle/NodeTestCradle.cs create mode 100644 Core/Stateflows.Testing/Activities/Cradle/NodeTestCradleBuilder.cs create mode 100644 Core/Stateflows.Testing/Activities/Cradle/TestResults.cs delete mode 100644 Core/Stateflows/Activities/Classes/ActivityFinal.cs create mode 100644 Core/Stateflows/Activities/Classes/ControlDecisionNode.cs create mode 100644 Core/Stateflows/Activities/Classes/TokensAccessor.cs create mode 100644 Core/Stateflows/Activities/Context/Classes/ActivityFlowContextAccessor.cs create mode 100644 Core/Stateflows/Activities/Context/Classes/ActivityNodeContextAccessor.cs create mode 100644 Core/Stateflows/Activities/Context/Classes/FlowContext.cs create mode 100644 Core/Stateflows/Activities/Context/Interfaces/IActivityFlowContext.cs delete mode 100644 Core/Stateflows/Activities/Context/Interfaces/IFlowContext.cs delete mode 100644 Core/Stateflows/Activities/Extensions/IEnumerableOfTokensExtensions.cs delete mode 100644 Core/Stateflows/Activities/Extensions/IOutputExtensions.cs delete mode 100644 Core/Stateflows/Activities/Extensions/OutputExtensions.cs create mode 100644 Core/Stateflows/Activities/Interfaces/ITokensAccessor.cs create mode 100644 Core/Stateflows/Activities/Registration/Interfaces/Base/IActivityUtils.cs delete mode 100644 Core/Stateflows/Activities/Registration/Interfaces/Extensions/AcceptEventActionBuilder/Flows/AcceptEventActionBuilderObjectFlowsPayloadExtensions.cs delete mode 100644 Core/Stateflows/Activities/Registration/Interfaces/Extensions/AcceptEventActionBuilder/Flows/AcceptEventActionBuilderObjectFlowsTypedPayloadExtensions.cs delete mode 100644 Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActionBuilder/Flows/ActionBuilderObjectFlowsPayloadExtensions.cs delete mode 100644 Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActionBuilder/Flows/ActionBuilderObjectFlowsTypedPayloadExtensions.cs delete mode 100644 Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActivityBuilder/ActivityBuilderSpecialsPayloadExtensions.cs delete mode 100644 Core/Stateflows/Activities/Registration/Interfaces/Extensions/DataStoreBuilder/Flows/DataStoreBuilderFlowsPayloadExtensions.cs delete mode 100644 Core/Stateflows/Activities/Registration/Interfaces/Extensions/DataStoreBuilder/Flows/DataStoreBuilderFlowsTypedPayloadExtensions.cs delete mode 100644 Core/Stateflows/Activities/Registration/Interfaces/Extensions/DecisionBuilder/ElseFlows/DecisionBuilderElseObjectFlowsPayloadExtensions.cs delete mode 100644 Core/Stateflows/Activities/Registration/Interfaces/Extensions/DecisionBuilder/ElseFlows/DecisionBuilderElseObjectFlowsTypedPayloadExtensions.cs delete mode 100644 Core/Stateflows/Activities/Registration/Interfaces/Extensions/DecisionBuilder/Flows/DecisionBuilderObjectFlowsPayloadExtensions.cs delete mode 100644 Core/Stateflows/Activities/Registration/Interfaces/Extensions/DecisionBuilder/Flows/DecisionBuilderObjectFlowsTypedPayloadExtensions.cs delete mode 100644 Core/Stateflows/Activities/Registration/Interfaces/Extensions/InputBuilder/Flows/InputBuilderFlowsPayloadExtensions.cs delete mode 100644 Core/Stateflows/Activities/Registration/Interfaces/Extensions/InputBuilder/Flows/InputBuilderFlowsTypedPayloadExtensions.cs delete mode 100644 Core/Stateflows/Activities/Registration/Interfaces/Extensions/JoinBuilder/Flows/JoinBuilderFlowsPayloadExtensions.cs delete mode 100644 Core/Stateflows/Activities/Registration/Interfaces/Extensions/JoinBuilder/Flows/JoinBuilderFlowsTypedPayloadExtensions.cs delete mode 100644 Core/Stateflows/Activities/Registration/Interfaces/Extensions/MergeBuilder/Flows/MergeBuilderObjectFlowsPayloadExtensions.cs delete mode 100644 Core/Stateflows/Activities/Registration/Interfaces/Extensions/MergeBuilder/Flows/MergeBuilderObjectFlowsTypedPayloadExtensions.cs delete mode 100644 Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/Flows/ReactiveStructuredActivityBuilderFlowsPayloadExtensions.cs delete mode 100644 Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/Flows/ReactiveStructuredActivityBuilderFlowsTypedPayloadExtensions.cs delete mode 100644 Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/ReactiveStructuredActivityBuilderSpecialsPayloadExtensions.cs delete mode 100644 Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/Flows/StructuredActivityBuilderFlowsPayloadExtensions.cs delete mode 100644 Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/Flows/StructuredActivityBuilderFlowsTypedPayloadExtensions.cs delete mode 100644 Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/StructuredActivityBuilderSpecialsPayloadExtensions.cs delete mode 100644 Core/Stateflows/Activities/Registration/Interfaces/Extensions/TypedActionBuilder/Flows/TypedActionBuilderFlowsPayloadExtensions.cs delete mode 100644 Core/Stateflows/Activities/Registration/Interfaces/Extensions/TypedActionBuilder/Flows/TypedActionBuilderFlowsTypedPayloadExtensions.cs delete mode 100644 Core/Stateflows/Activities/Registration/Interfaces/Extensions/TypedActivityBuilder/TypedActivityBuilderSpecialsPayloadExtensions.cs delete mode 100644 Core/Stateflows/Activities/Streams/NodeStreams.cs create mode 100644 Core/Stateflows/Activities/Tokens/Control.cs delete mode 100644 Core/Stateflows/Activities/Tokens/ControlToken.cs delete mode 100644 Core/Stateflows/Activities/Tokens/EventToken.cs create mode 100644 Core/Stateflows/Activities/Tokens/ExceptionHolder.cs delete mode 100644 Core/Stateflows/Activities/Tokens/ExceptionToken.cs create mode 100644 Core/Stateflows/Activities/Tokens/NodeReference.cs create mode 100644 Core/Stateflows/Activities/Tokens/TokenHolder.cs create mode 100644 Core/Stateflows/Activities/Utils/ObjectExtensions.cs create mode 100644 Core/Stateflows/Common/Classes/BaseValueAccessor.cs create mode 100644 Core/Stateflows/Common/Classes/GlobalValueAccessors.cs create mode 100644 Core/Stateflows/Common/Classes/ValueAccessors.cs create mode 100644 Core/Stateflows/GlobalSuppressions.cs create mode 100644 Extensions/Stateflows.Extensions.Logging/ActivityTracer.cs create mode 100644 Extensions/Stateflows.Extensions.Logging/DependencyInjection.cs create mode 100644 Extensions/Stateflows.Extensions.Logging/StateMachineTracer.cs create mode 100644 Extensions/Stateflows.Extensions.Logging/Stateflows.Extensions.Logging.csproj create mode 100644 Tests/Activity.IntegrationTests/Classes/Tokens/SomeToken.cs create mode 100644 Tests/Activity.IntegrationTests/Tests/AcceptEvent.cs create mode 100644 Tests/Activity.IntegrationTests/Tests/ActionUnit.cs create mode 100644 Tests/Activity.IntegrationTests/Tests/Context.cs create mode 100644 Tests/Activity.IntegrationTests/Tests/DataStore.cs create mode 100644 Tests/Activity.IntegrationTests/Tests/Decision.cs create mode 100644 Tests/Activity.IntegrationTests/Tests/Fork.cs create mode 100644 Tests/Activity.IntegrationTests/Tests/Iterative.cs create mode 100644 Tests/Activity.IntegrationTests/Tests/Join.cs create mode 100644 Tests/Activity.IntegrationTests/Tests/Merge.cs create mode 100644 Tests/Activity.IntegrationTests/Tests/Parallel.cs create mode 100644 Tests/Activity.IntegrationTests/Tests/Structured.cs create mode 100644 Tests/Activity.IntegrationTests/Tests/TokenIdentity.cs create mode 100644 Tests/Activity.IntegrationTests/Tests/Typed.cs create mode 100644 Tests/Activity.IntegrationTests/Tests/Values.cs create mode 100644 Tests/Activity.IntegrationTests/Tests/Weight.cs create mode 100644 Tests/StateMachine/StateMachine.IntegrationTests/Classes/StateMachines/ValuesStateMachine.cs create mode 100644 Tests/StateMachine/StateMachine.IntegrationTests/Classes/States/ValueState1.cs create mode 100644 Tests/StateMachine/StateMachine.IntegrationTests/Classes/States/ValueState2.cs create mode 100644 Tests/StateMachine/StateMachine.IntegrationTests/Classes/Transitions/GuardedTransition.cs create mode 100644 Tests/StateMachine/StateMachine.IntegrationTests/Classes/Transitions/InternalTransition.cs create mode 100644 Tests/StateMachine/StateMachine.IntegrationTests/Classes/Transitions/ValueTransition.cs create mode 100644 Tests/StateMachine/StateMachine.IntegrationTests/Tests/Context.cs create mode 100644 Tests/StateMachine/StateMachine.IntegrationTests/Tests/Values.cs diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..d9ad58cd --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ +[*.cs] + +# S3358: Ternary operators should not be nested +dotnet_diagnostic.S3358.severity = none + +# S2094: Classes should not be empty +dotnet_diagnostic.S2094.severity = none +dotnet_diagnostic.S2326.severity = none +dotnet_diagnostic.S1121.severity = none +dotnet_diagnostic.CS0067.severity = none \ No newline at end of file diff --git a/Core/Stateflows.Common/Activities/Classes/ActivityWrapper.cs b/Core/Stateflows.Common/Activities/Classes/ActivityWrapper.cs index cfd529f0..b6557bc4 100644 --- a/Core/Stateflows.Common/Activities/Classes/ActivityWrapper.cs +++ b/Core/Stateflows.Common/Activities/Classes/ActivityWrapper.cs @@ -17,9 +17,9 @@ public ActivityWrapper(IBehavior consumer) Behavior = consumer; } - public Task> ExecuteAsync(InitializationRequest initializationRequest = null, IEnumerable inputTokens = null) + public Task> ExecuteAsync(InitializationRequest initializationRequest = null, IEnumerable inputTokens = null) { - var executionRequest = new ExecutionRequest(initializationRequest ?? new InitializationRequest(), inputTokens ?? new Token[0]); + var executionRequest = new ExecutionRequest(initializationRequest ?? new InitializationRequest(), inputTokens ?? new object[0]); if (initializationRequest != null) { executionRequest.Headers.AddRange(initializationRequest.Headers); diff --git a/Core/Stateflows.Common/Activities/Events/ExecutionRequest.cs b/Core/Stateflows.Common/Activities/Events/ExecutionRequest.cs index ad430e92..f2d996c5 100644 --- a/Core/Stateflows.Common/Activities/Events/ExecutionRequest.cs +++ b/Core/Stateflows.Common/Activities/Events/ExecutionRequest.cs @@ -6,7 +6,7 @@ namespace Stateflows.Activities.Events { public sealed class ExecutionRequest : Request { - public ExecutionRequest(InitializationRequest initializationRequest, IEnumerable inputTokens) + public ExecutionRequest(InitializationRequest initializationRequest, IEnumerable inputTokens) { InitializationRequest = initializationRequest; InputTokens = inputTokens; @@ -15,6 +15,6 @@ public ExecutionRequest(InitializationRequest initializationRequest, IEnumerable public InitializationRequest InitializationRequest { get; set; } [JsonProperty(TypeNameHandling = TypeNameHandling.None)] - public IEnumerable InputTokens { get; set; } + public IEnumerable InputTokens { get; set; } } } diff --git a/Core/Stateflows.Common/Activities/Events/ExecutionResponse.cs b/Core/Stateflows.Common/Activities/Events/ExecutionResponse.cs index b53c2068..fe15d177 100644 --- a/Core/Stateflows.Common/Activities/Events/ExecutionResponse.cs +++ b/Core/Stateflows.Common/Activities/Events/ExecutionResponse.cs @@ -9,6 +9,6 @@ public sealed class ExecutionResponse : Response public bool ExecutionSuccessful { get; set; } [JsonProperty(TypeNameHandling = TypeNameHandling.None)] - public IEnumerable OutputTokens { get; set; } = new List(); + public IEnumerable OutputTokens { get; set; } = new List(); } } diff --git a/Core/Stateflows.Common/Activities/Extensions/ExecutionResponseExtensions.cs b/Core/Stateflows.Common/Activities/Extensions/ExecutionResponseExtensions.cs index 5223e2f7..c4708583 100644 --- a/Core/Stateflows.Common/Activities/Extensions/ExecutionResponseExtensions.cs +++ b/Core/Stateflows.Common/Activities/Extensions/ExecutionResponseExtensions.cs @@ -1,6 +1,5 @@ using System.Linq; using System.Collections.Generic; -using Stateflows.Common; using Stateflows.Activities.Events; namespace Stateflows.Activities @@ -9,7 +8,7 @@ public static class ExecutionResponseExtensions { public static IEnumerable GetOutputValues(this ExecutionResponse response) => response != null - ? response.OutputTokens.OfType>().Select(t => t.Payload).ToArray() + ? response.OutputTokens.OfType().ToArray() : new T[0]; public static T GetOutputValueOrDefault(this ExecutionResponse response, T defaultValue = default) diff --git a/Core/Stateflows.Common/Activities/Extensions/IBehaviorLocatorActivityExtensions.cs b/Core/Stateflows.Common/Activities/Extensions/IBehaviorLocatorActivityExtensions.cs index 911c6de1..8817761a 100644 --- a/Core/Stateflows.Common/Activities/Extensions/IBehaviorLocatorActivityExtensions.cs +++ b/Core/Stateflows.Common/Activities/Extensions/IBehaviorLocatorActivityExtensions.cs @@ -6,12 +6,10 @@ namespace Stateflows.Activities public static class IBehaviorLocatorActivityExtensions { public static bool TryLocateActivity(this IBehaviorLocator locator, ActivityId id, out IActivity activity) -#pragma warning disable S1121 // Assignments should not be made from within sub-expressions => ( activity = locator.TryLocateBehavior(id.BehaviorId, out var behavior) ? new ActivityWrapper(behavior) : null ) != null; -#pragma warning restore S1121 // Assignments should not be made from within sub-expressions } } diff --git a/Core/Stateflows.Common/Activities/Extensions/TokenInfoExtensions.cs b/Core/Stateflows.Common/Activities/Extensions/TokenInfoExtensions.cs deleted file mode 100644 index 1863a550..00000000 --- a/Core/Stateflows.Common/Activities/Extensions/TokenInfoExtensions.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using Stateflows.Common.Extensions; -using Stateflows.Common; - -namespace Stateflows.Activities -{ - public static class TokenInfoExtensions - { - public static string GetTokenName(this Type @type) - { - if (!@type.IsSubclassOf(typeof(Token))) - { - throw new ArgumentException("Given type is not subclass of Token class"); - } - - var token = @type.GetUninitializedInstance() as Token; - return token.Name; - } - } -} diff --git a/Core/Stateflows.Common/Activities/Interfaces/IActivity.cs b/Core/Stateflows.Common/Activities/Interfaces/IActivity.cs index 07d0f751..48cf455f 100644 --- a/Core/Stateflows.Common/Activities/Interfaces/IActivity.cs +++ b/Core/Stateflows.Common/Activities/Interfaces/IActivity.cs @@ -7,6 +7,6 @@ namespace Stateflows.Activities { public interface IActivity : IBehavior { - Task> ExecuteAsync(InitializationRequest initializationRequest = null, IEnumerable inputTokens = null); + Task> ExecuteAsync(InitializationRequest initializationRequest = null, IEnumerable inputTokens = null); } } diff --git a/Core/Stateflows.Common/Events/Event.cs b/Core/Stateflows.Common/Events/Event.cs index 3cff9c74..aeb3a6bd 100644 --- a/Core/Stateflows.Common/Events/Event.cs +++ b/Core/Stateflows.Common/Events/Event.cs @@ -5,12 +5,16 @@ namespace Stateflows.Common { - public class Event : Token + public class Event { + public Guid Id { get; set; } = Guid.NewGuid(); + [JsonProperty(TypeNameHandling = TypeNameHandling.None)] public List Headers { get; set; } = new List(); public DateTime SentAt { get; set; } + + public virtual string Name => GetType().GetEventName(); } public class Event : Event diff --git a/Core/Stateflows.Common/Events/TimeEvents/RecurringEvent.cs b/Core/Stateflows.Common/Events/TimeEvents/RecurringEvent.cs index c471e474..d8a77d6e 100644 --- a/Core/Stateflows.Common/Events/TimeEvents/RecurringEvent.cs +++ b/Core/Stateflows.Common/Events/TimeEvents/RecurringEvent.cs @@ -1,7 +1,5 @@ namespace Stateflows.Common { -#pragma warning disable S2094 // Classes should not be empty public abstract class RecurringEvent : TimeEvent -#pragma warning restore S2094 // Classes should not be empty { } } diff --git a/Core/Stateflows.Common/Extensions/EventInfoExtensions.cs b/Core/Stateflows.Common/Extensions/EventInfoExtensions.cs index 00013ee8..987f05e8 100644 --- a/Core/Stateflows.Common/Extensions/EventInfoExtensions.cs +++ b/Core/Stateflows.Common/Extensions/EventInfoExtensions.cs @@ -1,4 +1,5 @@ -using System; +using Stateflows.Common.Extensions; +using System; namespace Stateflows.Common { @@ -11,7 +12,7 @@ public static string GetEventName(this Type @type) throw new ArgumentException("Given type is not subclass of Event class"); } - return @type.GetTokenName(); + return @type.GetReadableName(); } } } diff --git a/Core/Stateflows.Common/Extensions/PayloadObjectExtensions.cs b/Core/Stateflows.Common/Extensions/PayloadObjectExtensions.cs index fc45e2d2..9fc24cdf 100644 --- a/Core/Stateflows.Common/Extensions/PayloadObjectExtensions.cs +++ b/Core/Stateflows.Common/Extensions/PayloadObjectExtensions.cs @@ -1,23 +1,14 @@ -using System.Linq; -using System.Collections.Generic; - -namespace Stateflows.Common.Data +namespace Stateflows.Common.Data { public static class PayloadObjectExtensions { - public static Event ToEvent(this T obj) - => new Event() { Payload = obj }; - - public static Request ToRequest(this TRequestPayload obj) - => new Request() { Payload = obj }; - - public static InitializationRequest ToInitializationRequest(this T obj) - => new InitializationRequest() { Payload = obj }; + public static Event ToEvent(this T payload) + => new Event() { Payload = payload }; - public static Token ToToken(this T obj) - => new Token() { Payload = obj }; + public static Request ToRequest(this TRequestPayload payload) + => new Request() { Payload = payload }; - public static IEnumerable> ToTokens(this IEnumerable objs) - => objs.Select(obj => obj.ToToken()).ToArray(); + public static InitializationRequest ToInitializationRequest(this TPayload payload) + => new InitializationRequest() { Payload = payload }; } } diff --git a/Core/Stateflows.Common/Extensions/TokenInfoExtensions.cs b/Core/Stateflows.Common/Extensions/TokenInfoExtensions.cs index 45cc6326..9b48ce45 100644 --- a/Core/Stateflows.Common/Extensions/TokenInfoExtensions.cs +++ b/Core/Stateflows.Common/Extensions/TokenInfoExtensions.cs @@ -6,14 +6,6 @@ namespace Stateflows.Common public static class TokenInfoExtensions { public static string GetTokenName(this Type @type) - { - if (!@type.IsSubclassOf(typeof(Token))) - { - throw new ArgumentException("Given type is not subclass of Token class"); - } - - var token = @type.GetUninitializedInstance() as Token; - return token.Name; - } + => @type.GetReadableName(); } } diff --git a/Core/Stateflows.Common/Extensions/TypeExtensions.cs b/Core/Stateflows.Common/Extensions/TypeExtensions.cs index 89245845..3bb88fb0 100644 --- a/Core/Stateflows.Common/Extensions/TypeExtensions.cs +++ b/Core/Stateflows.Common/Extensions/TypeExtensions.cs @@ -23,7 +23,7 @@ public static string GetReadableName(this Type type) var standardPrefix = "Stateflows.Activities."; if (result.StartsWith(standardPrefix)) { - result = result.Substring(standardPrefix.Length); + result = result[standardPrefix.Length..]; } return result; diff --git a/Core/Stateflows.Common/Interfaces/IBehavior.cs b/Core/Stateflows.Common/Interfaces/IBehavior.cs index 2909d731..93417a86 100644 --- a/Core/Stateflows.Common/Interfaces/IBehavior.cs +++ b/Core/Stateflows.Common/Interfaces/IBehavior.cs @@ -1,11 +1,13 @@ using System; using System.Linq; using System.Threading.Tasks; -using Stateflows.Common.Data; using Stateflows.Common.Interfaces; namespace Stateflows.Common { + /// + /// Behavior handle + /// public interface IBehavior : IWatches, IDisposable { BehaviorId Id { get; } @@ -41,9 +43,6 @@ async Task> ReinitializeAsync(Initializati return new RequestResult(initializationRequest, result.Status, result.Validation); } - Task> ReinitializeAsync(TInitializationPayload payload, bool keepVersion = true) - => ReinitializeAsync(payload.ToInitializationRequest(), keepVersion); - Task> GetStatusAsync() => RequestAsync(new BehaviorStatusRequest()); diff --git a/Core/Stateflows.Common/Interfaces/IBehaviorLocator.cs b/Core/Stateflows.Common/Interfaces/IBehaviorLocator.cs index 83965068..89634937 100644 --- a/Core/Stateflows.Common/Interfaces/IBehaviorLocator.cs +++ b/Core/Stateflows.Common/Interfaces/IBehaviorLocator.cs @@ -2,6 +2,12 @@ namespace Stateflows.Common { public interface IBehaviorLocator { + /// + /// Locates handle of behavior with given identifier. + /// + /// Identifier of behavior + /// out parameter providing behavior handle + /// True if behavior handle is available; false otherwise bool TryLocateBehavior(BehaviorId id, out IBehavior behavior); } } diff --git a/Core/Stateflows.Common/Interfaces/ISubscriptions.cs b/Core/Stateflows.Common/Interfaces/ISubscriptions.cs index f5b511c4..6e615dc0 100644 --- a/Core/Stateflows.Common/Interfaces/ISubscriptions.cs +++ b/Core/Stateflows.Common/Interfaces/ISubscriptions.cs @@ -4,9 +4,22 @@ namespace Stateflows.Common { public interface ISubscriptions { + /// + /// Subscribes for notifications from given behavior (by sending to it).
+ /// Subscription is durable over time; the only way to end it is by calling . + ///
+ /// Subscribed notification type + /// Identifier of a behavior being subscribed to + /// Task providing Task> SubscribeAsync(BehaviorId behaviorId) where TNotification : Notification, new(); + /// + /// Unsubscribes for notifications from given behavior (by sending to it). + /// + /// Unsubscribed notification type + /// Identifier of a behavior being unsubscribed to + /// Task providing Task> UnsubscribeAsync(BehaviorId behaviorId) where TNotification : Notification, new(); } diff --git a/Core/Stateflows.Common/Interfaces/IWatches.cs b/Core/Stateflows.Common/Interfaces/IWatches.cs index 0c00995a..ab63ff0e 100644 --- a/Core/Stateflows.Common/Interfaces/IWatches.cs +++ b/Core/Stateflows.Common/Interfaces/IWatches.cs @@ -5,9 +5,21 @@ namespace Stateflows.Common.Interfaces { public interface IWatches { + /// + /// Watches for notifications from behavior.
+ /// Watch is not durable; it lasts as long as behavior handle does. + ///
+ /// Notification type + /// Notification handler + /// Task of watch operation Task WatchAsync(Action handler) where TNotification : Notification, new(); + /// + /// Unwatches for notifications from behavior. + /// + /// Notification type + /// Task of unwatch operation Task UnwatchAsync() where TNotification : Notification, new(); } diff --git a/Core/Stateflows.Common/Tokens/GroupToken.cs b/Core/Stateflows.Common/Tokens/GroupToken.cs deleted file mode 100644 index 246147e8..00000000 --- a/Core/Stateflows.Common/Tokens/GroupToken.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Collections.Generic; - -namespace Stateflows.Common -{ - public sealed class GroupToken : Token - where TToken : Token, new() - { - public GroupToken() - { } - - public override string Name - => $"Stateflows.Activities.GroupToken<{TokenInfo.Name}>"; - - public List Tokens { get; set; } = new List(); - } -} diff --git a/Core/Stateflows.Common/Tokens/Token.cs b/Core/Stateflows.Common/Tokens/Token.cs deleted file mode 100644 index 0ae19097..00000000 --- a/Core/Stateflows.Common/Tokens/Token.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Linq; -using System.Collections.Generic; -using Stateflows.Common.Utilities; -using Stateflows.Common.Extensions; - -namespace Stateflows.Common -{ - public class Token - { - public Guid Id { get; set; } = Guid.NewGuid(); - - public virtual string Name => GetType().GetReadableName(); - } - - public class Token : Token - { - public Token() - { - Payload = default; - } - - public T Payload { get; set; } - } - - public static class TokenExtensions - { - public static TToken CloneToken(this TToken token) - where TToken : Token, new() - { - var clonedToken = StateflowsJsonConverter.CloneObject(token); - clonedToken.Id = Guid.NewGuid(); - return clonedToken; - } - - public static IEnumerable CloneTokens(this IEnumerable tokens) - where TToken : Token, new() - => tokens.Select(token => token.CloneToken()).ToArray(); - } - - public static class TokenInfo - where TToken : Token, new() - { - public static string Name => TokenInfo.GetName(typeof(TToken)); - } - - public static class TokenInfo - { - public static string GetName(Type @type) - => (type.GetUninitializedInstance() as Token).Name; - } -} diff --git a/Core/Stateflows.Common/Utilities/BehaviorExtensions.cs b/Core/Stateflows.Common/Utilities/BehaviorExtensions.cs deleted file mode 100644 index 10198d61..00000000 --- a/Core/Stateflows.Common/Utilities/BehaviorExtensions.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Linq; -using System.Threading.Tasks; -using System.Collections.Generic; -using Stateflows.Common.Data; -using Stateflows.StateMachines.Events; -using System; - -namespace Stateflows.Common -{ - public static class BehaviorExtensions - { - // public static Task> ResetAsync(this IBehavior behavior, bool keepVersion = false) - // => behavior.RequestAsync(new ResetRequest() { KeepVersion = keepVersion }); - - // public static async Task> ReinitializeAsync(this IBehavior behavior, InitializationRequest initializationRequest = null, bool keepVersion = true) - // { - // initializationRequest ??= new InitializationRequest(); - // var compoundResult = await behavior.RequestAsync( - // new CompoundRequest() - // { - // Events = new List() - // { - // new ResetRequest() { KeepVersion = keepVersion }, - // initializationRequest - // } - // } - // ); - - // var result = compoundResult.Response.Results.Last(); - - // return new RequestResult(initializationRequest, result.Status, result.Validation); - // } - - // public static Task> ReinitializeAsync(this IBehavior behavior, TInitializationPayload payload, bool keepVersion = true) - // => behavior.ReinitializeAsync(payload.ToInitializationRequest(), keepVersion); - - // public static Task> GetStatusAsync(this IBehavior behavior) - // => behavior.RequestAsync(new BehaviorStatusRequest()); - - // public static Task WatchStatusAsync(this IBehavior behavior, Action handler) - // => behavior.WatchAsync(handler); - - // public static Task UnwatchStatusAsync(this IBehavior behavior) - // => behavior.UnwatchAsync(); - } -} \ No newline at end of file diff --git a/Core/Stateflows.Common/Utilities/DataBehaviorExtensions.cs b/Core/Stateflows.Common/Utilities/DataBehaviorExtensions.cs index 625005fc..49f6d0ae 100644 --- a/Core/Stateflows.Common/Utilities/DataBehaviorExtensions.cs +++ b/Core/Stateflows.Common/Utilities/DataBehaviorExtensions.cs @@ -7,6 +7,9 @@ public static class DataBehaviorExtensions public static Task> InitializeAsync(this IBehavior behavior, TInitializationPayload payload) => behavior.InitializeAsync(payload.ToInitializationRequest()); + public static Task> ReinitializeAsync(this IBehavior behavior, TPayload payload, bool keepVersion = true) + => behavior.ReinitializeAsync(payload.ToInitializationRequest(), keepVersion); + public static Task SendAsync(this IBehavior behavior, TEventPayload payload) => behavior.SendAsync(payload.ToEvent()); diff --git a/Core/Stateflows.Common/Utilities/StateflowsJsonConverter.cs b/Core/Stateflows.Common/Utilities/StateflowsJsonConverter.cs index acd1c0a0..20b7dd1c 100644 --- a/Core/Stateflows.Common/Utilities/StateflowsJsonConverter.cs +++ b/Core/Stateflows.Common/Utilities/StateflowsJsonConverter.cs @@ -7,26 +7,26 @@ namespace Stateflows.Common.Utilities { public static class StateflowsJsonConverter { - private static JsonSerializerSettings polymorphicCamelSettings = new JsonSerializerSettings() + private static readonly JsonSerializerSettings polymorphicCamelSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All, ReferenceLoopHandling = ReferenceLoopHandling.Ignore, ContractResolver = new CamelCasePropertyNamesContractResolver() }; - private static JsonSerializerSettings polymorphicSettings = new JsonSerializerSettings() + private static readonly JsonSerializerSettings polymorphicSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All, ReferenceLoopHandling = ReferenceLoopHandling.Ignore }; - private static JsonSerializerSettings camelSettings = new JsonSerializerSettings() + private static readonly JsonSerializerSettings camelSettings = new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore, ContractResolver = new CamelCasePropertyNamesContractResolver() }; - private static JsonSerializerSettings settings = new JsonSerializerSettings() + private static readonly JsonSerializerSettings settings = new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore }; diff --git a/Core/Stateflows.Testing/Activities/Cradle/Context/ActivityContext.cs b/Core/Stateflows.Testing/Activities/Cradle/Context/ActivityContext.cs new file mode 100644 index 00000000..5e60ad9a --- /dev/null +++ b/Core/Stateflows.Testing/Activities/Cradle/Context/ActivityContext.cs @@ -0,0 +1,40 @@ +using Stateflows.Activities; +using Stateflows.Activities.Context.Interfaces; +using Stateflows.Common; +using Stateflows.Common.Context.Interfaces; +using Stateflows.Common.Interfaces; +using System.Threading.Tasks; + +namespace Stateflows.Testing.Activities.Cradle.Context +{ + internal class ActivityContext : IActivityContext + { + public ActivityId Id { get; internal set; } + + public object LockHandle => this; + + public IContextValues Values => throw new global::System.NotImplementedException(); + + BehaviorId IBehaviorContext.Id => Id; + + public void Publish(TNotification notification) where TNotification : Notification, new() + { + throw new global::System.NotImplementedException(); + } + + public void Send(TEvent @event) where TEvent : Event, new() + { + throw new global::System.NotImplementedException(); + } + + public Task> SubscribeAsync(BehaviorId behaviorId) where TNotification : Notification, new() + { + throw new global::System.NotImplementedException(); + } + + public Task> UnsubscribeAsync(BehaviorId behaviorId) where TNotification : Notification, new() + { + throw new global::System.NotImplementedException(); + } + } +} diff --git a/Core/Stateflows.Testing/Activities/Cradle/Context/NodeContext.cs b/Core/Stateflows.Testing/Activities/Cradle/Context/NodeContext.cs new file mode 100644 index 00000000..de41fe97 --- /dev/null +++ b/Core/Stateflows.Testing/Activities/Cradle/Context/NodeContext.cs @@ -0,0 +1,22 @@ +using Stateflows.Activities; +using Stateflows.Activities.Context.Interfaces; +using System.Collections.Generic; + +namespace Stateflows.Testing.Activities.Cradle.Context +{ + internal class NodeContext : INodeContext + { + public string NodeName { get; internal set; } + + public NodeType NodeType { get; internal set; } + + public INodeContext ParentNode { get; internal set; } + + public IEnumerable IncomingFlows { get; internal set; } + + public IEnumerable OutgoingFlows { get; internal set; } + + public bool TryGetParentNode(out INodeContext parentNodeContext) + => (parentNodeContext = ParentNode) != null; + } +} diff --git a/Core/Stateflows.Testing/Activities/Cradle/Context/TypedActionContext.cs b/Core/Stateflows.Testing/Activities/Cradle/Context/TypedActionContext.cs new file mode 100644 index 00000000..ced123bc --- /dev/null +++ b/Core/Stateflows.Testing/Activities/Cradle/Context/TypedActionContext.cs @@ -0,0 +1,24 @@ +using System; +using System.Threading; +using Stateflows.Common; +using Stateflows.Activities.Context.Interfaces; + +namespace Stateflows.Testing.Activities.Cradle.Context +{ + internal class TypedActionContext : ITypedActionContext + { + internal NodeContext currentNode; + public INodeContext CurrentNode => currentNode ??= new NodeContext(); + + internal CancellationToken cancellationToken; + public CancellationToken CancellationToken => cancellationToken; + + internal ActivityContext activity; + public IActivityContext Activity => activity ??= new ActivityContext(); + + public bool TryLocateBehavior(BehaviorId id, out IBehavior behavior) + { + throw new NotImplementedException(); + } + } +} diff --git a/Core/Stateflows.Testing/Activities/Cradle/FlowTestCradle.cs b/Core/Stateflows.Testing/Activities/Cradle/FlowTestCradle.cs new file mode 100644 index 00000000..ed078745 --- /dev/null +++ b/Core/Stateflows.Testing/Activities/Cradle/FlowTestCradle.cs @@ -0,0 +1,40 @@ +using System.Threading.Tasks; +using System.Collections.Generic; +using Stateflows.Activities; +using Stateflows.Common.Interfaces; + +namespace Stateflows.Testing.Activities.Cradle +{ + internal class FlowTestCradle : ITestCradle + { + private readonly Flow testedFlow; + + private readonly List inputTokens; + + private readonly IContextValues contextValues; + + public FlowTestCradle(Flow flow, List inputTokens, IContextValues contextValues) + { + testedFlow = flow; + this.inputTokens = inputTokens; + this.contextValues = contextValues; + } + + private readonly List outputTokens = new List(); + + async Task ITestCradle.SwingAsync() + { + InputTokensHolder.Tokens.Value = inputTokens; + OutputTokensHolder.Tokens.Value = outputTokens; + + if (await testedFlow.GuardAsync()) + { + } + + InputTokensHolder.Tokens.Value = null; + OutputTokensHolder.Tokens.Value = null; + + return new TestResults(outputTokens, contextValues); + } + } +} diff --git a/Core/Stateflows.Testing/Activities/Cradle/FlowTestCradleBuilder.cs b/Core/Stateflows.Testing/Activities/Cradle/FlowTestCradleBuilder.cs new file mode 100644 index 00000000..e3050a1b --- /dev/null +++ b/Core/Stateflows.Testing/Activities/Cradle/FlowTestCradleBuilder.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using Stateflows.Activities; +using Stateflows.Common.Classes; +using Stateflows.Common.Interfaces; +using Microsoft.Extensions.DependencyInjection; + +namespace Stateflows.Testing.Activities.Cradle +{ + internal class FlowTestCradleBuilder : IFlowTestCradleBuilder, IFlowTestCradleBuilderWithInput + where TActionNode : Flow + { + private readonly IServiceProvider serviceProvider; + + public FlowTestCradleBuilder(IServiceProvider serviceProvider) + { + this.serviceProvider = serviceProvider; + } + + private readonly Dictionary contextValuesCollection = new Dictionary(); + private IContextValues contextValues; + private IContextValues ContextValues + => contextValues ??= new ContextValues(contextValuesCollection); + + private readonly List InputTokens = new List(); + + IFlowTestCradleBuilderWithInput IFlowTestCradleBuilderWithInput.AddGlobalContextValue(string key, T value) + { + ContextValues.Set(key, value); + + return this; + } + + IFlowTestCradleBuilderWithInput IFlowTestCradleBuilder.AddInputToken(TToken token) + { + InputTokens.Add(new TokenHolder() { Payload = token }); + + return this; + } + + ITestCradle IFlowTestCradleBuilderWithInput.Build() + { + ContextValuesHolder.GlobalValues.Value = ContextValues; + ContextValuesHolder.StateValues.Value = null; + ContextValuesHolder.SourceStateValues.Value = null; + ContextValuesHolder.TargetStateValues.Value = null; + + return new FlowTestCradle(serviceProvider.GetService(), InputTokens, ContextValues); + } + } +} diff --git a/Core/Stateflows.Testing/Activities/Cradle/IFlowTestCradleBuilder.cs b/Core/Stateflows.Testing/Activities/Cradle/IFlowTestCradleBuilder.cs new file mode 100644 index 00000000..ffd69c31 --- /dev/null +++ b/Core/Stateflows.Testing/Activities/Cradle/IFlowTestCradleBuilder.cs @@ -0,0 +1,13 @@ +namespace Stateflows.Testing.Activities.Cradle +{ + public interface IFlowTestCradleBuilderWithInput + { + public IFlowTestCradleBuilderWithInput AddGlobalContextValue(string name, T value); + public ITestCradle Build(); + } + + public interface IFlowTestCradleBuilder + { + public IFlowTestCradleBuilderWithInput AddInputToken(TToken token); + } +} diff --git a/Core/Stateflows.Testing/Activities/Cradle/INodeTestCradleBuilder.cs b/Core/Stateflows.Testing/Activities/Cradle/INodeTestCradleBuilder.cs new file mode 100644 index 00000000..ec07515d --- /dev/null +++ b/Core/Stateflows.Testing/Activities/Cradle/INodeTestCradleBuilder.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; + +namespace Stateflows.Testing.Activities.Cradle +{ + public interface INodeTestCradleBuilder + { + public INodeTestCradleBuilder AddGlobalContextValue(string name, T value); + public INodeTestCradleBuilder AddInputToken(T token); + public INodeTestCradleBuilder AddInputTokens(IEnumerable tokens); + public ITestCradle Build(); + } +} diff --git a/Core/Stateflows.Testing/Activities/Cradle/ITestCradle.cs b/Core/Stateflows.Testing/Activities/Cradle/ITestCradle.cs new file mode 100644 index 00000000..7ac757aa --- /dev/null +++ b/Core/Stateflows.Testing/Activities/Cradle/ITestCradle.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace Stateflows.Testing.Activities.Cradle +{ + public interface ITestCradle + { + public Task SwingAsync(); + } +} diff --git a/Core/Stateflows.Testing/Activities/Cradle/ITestResults.cs b/Core/Stateflows.Testing/Activities/Cradle/ITestResults.cs new file mode 100644 index 00000000..f5c9ad7a --- /dev/null +++ b/Core/Stateflows.Testing/Activities/Cradle/ITestResults.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; + +namespace Stateflows.Testing.Activities.Cradle +{ + public interface ITestResults + { + bool IsGlobalContextValueSet(string key); + public bool TryGetGlobalContextValue(string key, out T value); + public IEnumerable GetOutputTokens(); + } +} diff --git a/Core/Stateflows.Testing/Activities/Cradle/NodeTestCradle.cs b/Core/Stateflows.Testing/Activities/Cradle/NodeTestCradle.cs new file mode 100644 index 00000000..e8e4c5ce --- /dev/null +++ b/Core/Stateflows.Testing/Activities/Cradle/NodeTestCradle.cs @@ -0,0 +1,38 @@ +using System.Threading.Tasks; +using System.Collections.Generic; +using Stateflows.Activities; +using Stateflows.Common.Interfaces; + +namespace Stateflows.Testing.Activities.Cradle +{ + internal class NodeTestCradle : ITestCradle + { + private readonly ActionNode testedNode; + + private readonly List inputTokens; + + private readonly IContextValues contextValues; + + public NodeTestCradle(ActionNode node, List inputTokens, IContextValues contextValues) + { + testedNode = node; + this.inputTokens = inputTokens; + this.contextValues = contextValues; + } + + private readonly List outputTokens = new List(); + + async Task ITestCradle.SwingAsync() + { + InputTokensHolder.Tokens.Value = inputTokens; + OutputTokensHolder.Tokens.Value = outputTokens; + + await testedNode.ExecuteAsync(); + + InputTokensHolder.Tokens.Value = null; + OutputTokensHolder.Tokens.Value = null; + + return new TestResults(outputTokens, contextValues); + } + } +} diff --git a/Core/Stateflows.Testing/Activities/Cradle/NodeTestCradleBuilder.cs b/Core/Stateflows.Testing/Activities/Cradle/NodeTestCradleBuilder.cs new file mode 100644 index 00000000..7f1a17f8 --- /dev/null +++ b/Core/Stateflows.Testing/Activities/Cradle/NodeTestCradleBuilder.cs @@ -0,0 +1,59 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using Stateflows.Activities; +using Stateflows.Common.Classes; +using Stateflows.Common.Interfaces; +using Microsoft.Extensions.DependencyInjection; + +namespace Stateflows.Testing.Activities.Cradle +{ + internal class NodeTestCradleBuilder : INodeTestCradleBuilder + where TActionNode : ActionNode + { + private readonly IServiceProvider serviceProvider; + + public NodeTestCradleBuilder(IServiceProvider serviceProvider) + { + this.serviceProvider = serviceProvider; + } + + private readonly Dictionary contextValuesCollection = new Dictionary(); + private IContextValues contextValues; + private IContextValues ContextValues + => contextValues ??= new ContextValues(contextValuesCollection); + + private readonly List InputTokens = new List(); + + INodeTestCradleBuilder INodeTestCradleBuilder.AddGlobalContextValue(string key, T value) + { + ContextValues.Set(key, value); + + return this; + } + + INodeTestCradleBuilder INodeTestCradleBuilder.AddInputToken(T token) + { + InputTokens.Add(new TokenHolder() { Payload = token }); + + return this; + } + + INodeTestCradleBuilder INodeTestCradleBuilder.AddInputTokens(IEnumerable tokens) + { + InputTokens.AddRange(tokens.Select(token => new TokenHolder() { Payload = token })); + + return this; + } + + ITestCradle INodeTestCradleBuilder.Build() + { + ContextValuesHolder.GlobalValues.Value = ContextValues; + ContextValuesHolder.StateValues.Value = null; + ContextValuesHolder.SourceStateValues.Value = null; + ContextValuesHolder.TargetStateValues.Value = null; + + return new NodeTestCradle(serviceProvider.GetService(), InputTokens, ContextValues); + } + } +} diff --git a/Core/Stateflows.Testing/Activities/Cradle/TestResults.cs b/Core/Stateflows.Testing/Activities/Cradle/TestResults.cs new file mode 100644 index 00000000..ac2ccb11 --- /dev/null +++ b/Core/Stateflows.Testing/Activities/Cradle/TestResults.cs @@ -0,0 +1,28 @@ +using System.Linq; +using System.Collections.Generic; +using Stateflows.Activities; +using Stateflows.Common.Interfaces; + +namespace Stateflows.Testing.Activities.Cradle +{ + internal class TestResults : ITestResults + { + public TestResults(List outputTokens, IContextValues contextValues) + { + this.outputTokens = outputTokens; + this.contextValues = contextValues; + } + + private readonly List outputTokens; + private readonly IContextValues contextValues; + + bool ITestResults.IsGlobalContextValueSet(string key) + => contextValues.IsSet(key); + + bool ITestResults.TryGetGlobalContextValue(string key, out T value) + => contextValues.TryGet(key, out value); + + IEnumerable ITestResults.GetOutputTokens() + => outputTokens.OfType>().Select(holder => holder.Payload).ToArray(); + } +} diff --git a/Core/Stateflows.Testing/StateflowsTestClass.cs b/Core/Stateflows.Testing/StateflowsTestClass.cs index 54d4897c..12792bdf 100644 --- a/Core/Stateflows.Testing/StateflowsTestClass.cs +++ b/Core/Stateflows.Testing/StateflowsTestClass.cs @@ -4,13 +4,14 @@ using System.Threading.Tasks; using System.Collections.Generic; using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.DependencyInjection; using Stateflows; +using Stateflows.Activities; using Stateflows.StateMachines; using Stateflows.Common.Registration.Interfaces; +using Stateflows.Testing.Activities.Cradle; using Stateflows.Testing.StateMachines.Sequence; -using Microsoft.Extensions.Logging; -using Stateflows.Activities; namespace StateMachine.IntegrationTests.Utils { @@ -26,6 +27,14 @@ public abstract class StateflowsTestClass protected IActivityLocator ActivityLocator => ServiceProvider.GetRequiredService(); + //protected IFlowTestCradleBuilder SetupCradle() + // where TFlow : Flow + // => new FlowTestCradleBuilder(ServiceProvider); + + protected INodeTestCradleBuilder SetupCradle() + where TActionNode : ActionNode + => new NodeTestCradleBuilder(ServiceProvider); + protected ExecutionSequenceObserver ExecutionSequence => ServiceProvider.GetRequiredService(); public virtual void Initialize() diff --git a/Core/Stateflows.Transport.Common/Stateflows.Common.Transport.csproj b/Core/Stateflows.Transport.Common/Stateflows.Common.Transport.csproj index bb2faf7a..3b3de483 100644 --- a/Core/Stateflows.Transport.Common/Stateflows.Common.Transport.csproj +++ b/Core/Stateflows.Transport.Common/Stateflows.Common.Transport.csproj @@ -35,8 +35,4 @@ - - - - diff --git a/Core/Stateflows/Activities/Classes/AcceptEventActionNode.cs b/Core/Stateflows/Activities/Classes/AcceptEventActionNode.cs index b003f4a1..324b7e09 100644 --- a/Core/Stateflows/Activities/Classes/AcceptEventActionNode.cs +++ b/Core/Stateflows/Activities/Classes/AcceptEventActionNode.cs @@ -3,9 +3,10 @@ namespace Stateflows.Activities { - public abstract class AcceptEventActionNode : ActionNode + public abstract class AcceptEventActionNode : BaseActionNode where TEvent : Event, new() { - public new IAcceptEventActionContext Context { get; internal set; } + public new IAcceptEventActionContext Context + => (IAcceptEventActionContext)base.Context; } } diff --git a/Core/Stateflows/Activities/Classes/ActionNode.cs b/Core/Stateflows/Activities/Classes/ActionNode.cs index c535c95b..47d2742d 100644 --- a/Core/Stateflows/Activities/Classes/ActionNode.cs +++ b/Core/Stateflows/Activities/Classes/ActionNode.cs @@ -2,8 +2,11 @@ namespace Stateflows.Activities { - public abstract class ActionNode : ActivityNode + public abstract class BaseActionNode : ActivityNode { public abstract Task ExecuteAsync(); } + + public abstract class ActionNode : BaseActionNode + { } } diff --git a/Core/Stateflows/Activities/Classes/ActivityFinal.cs b/Core/Stateflows/Activities/Classes/ActivityFinal.cs deleted file mode 100644 index cf44a251..00000000 --- a/Core/Stateflows/Activities/Classes/ActivityFinal.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Stateflows.Common.Extensions; - -namespace Stateflows.Activities -{ - public abstract class ActivityFinal : ActivityNode - { - public static string Name => typeof(ActivityFinal).GetReadableName(); - } -} diff --git a/Core/Stateflows/Activities/Classes/ActivityNode.cs b/Core/Stateflows/Activities/Classes/ActivityNode.cs index 12173a49..16def715 100644 --- a/Core/Stateflows/Activities/Classes/ActivityNode.cs +++ b/Core/Stateflows/Activities/Classes/ActivityNode.cs @@ -1,11 +1,13 @@ -using Stateflows.Activities.Context.Interfaces; -using Stateflows.Common.Extensions; +using Stateflows.Common.Extensions; +using Stateflows.Activities.Context.Classes; +using Stateflows.Activities.Context.Interfaces; namespace Stateflows.Activities { public abstract class ActivityNode { - public ITypedActionContext Context { get; internal set; } + public ITypedActionContext Context + => (ITypedActionContext)ActivityNodeContextAccessor.Context.Value; } public static class ActivityNodeInfo diff --git a/Core/Stateflows/Activities/Classes/ControlDecisionNode.cs b/Core/Stateflows/Activities/Classes/ControlDecisionNode.cs new file mode 100644 index 00000000..8be9676b --- /dev/null +++ b/Core/Stateflows/Activities/Classes/ControlDecisionNode.cs @@ -0,0 +1,9 @@ +using Stateflows.Common.Extensions; + +namespace Stateflows.Activities +{ + public sealed class ControlDecisionNode : ActivityNode + { + public static string Name => typeof(DecisionNode).GetReadableName(); + } +} diff --git a/Core/Stateflows/Activities/Classes/DecisionNode.cs b/Core/Stateflows/Activities/Classes/DecisionNode.cs index d979ae2e..c8955b55 100644 --- a/Core/Stateflows/Activities/Classes/DecisionNode.cs +++ b/Core/Stateflows/Activities/Classes/DecisionNode.cs @@ -1,10 +1,8 @@ -using Stateflows.Common; -using Stateflows.Common.Extensions; +using Stateflows.Common.Extensions; namespace Stateflows.Activities { public sealed class DecisionNode : ActivityNode - where TToken : Token, new() { public static string Name => typeof(DecisionNode).GetReadableName(); } diff --git a/Core/Stateflows/Activities/Classes/ElseFlow.cs b/Core/Stateflows/Activities/Classes/ElseFlow.cs index 0a7adec5..46fb09d3 100644 --- a/Core/Stateflows/Activities/Classes/ElseFlow.cs +++ b/Core/Stateflows/Activities/Classes/ElseFlow.cs @@ -1,24 +1,20 @@ using System.Threading.Tasks; -using Stateflows.Common; namespace Stateflows.Activities { - public abstract class ElseControlFlow : BaseControlFlow - { - public override sealed Task GuardAsync() - => Task.FromResult(true); - } + //public abstract class ElseControlFlow : BaseControlFlow + //{ + // public override sealed Task GuardAsync() + // => Task.FromResult(true); + //} - public abstract class ElseFlow : BaseFlow - where TToken : Token, new() - { - public override sealed Task GuardAsync() - => Task.FromResult(true); - } + //public abstract class ElseFlow : BaseFlow + //{ + // public override sealed Task GuardAsync() + // => Task.FromResult(true); + //} - public abstract class ElseObjectTransformationFlow : BaseTransformationFlow - where TToken : Token, new() - where TTransformedToken : Token, new() + public abstract class ElseTransformationFlow : BaseTransformationFlow { public override sealed Task GuardAsync() => Task.FromResult(true); diff --git a/Core/Stateflows/Activities/Classes/ExceptionHandlerNode.cs b/Core/Stateflows/Activities/Classes/ExceptionHandlerNode.cs index df6c2104..7d27ce22 100644 --- a/Core/Stateflows/Activities/Classes/ExceptionHandlerNode.cs +++ b/Core/Stateflows/Activities/Classes/ExceptionHandlerNode.cs @@ -7,7 +7,7 @@ namespace Stateflows.Activities public abstract class ExceptionHandlerNode : ActivityNode where TException : Exception { - new public IExceptionHandlerContext Context { get; internal set; } + new public IExceptionHandlerContext Context => base.Context as IExceptionHandlerContext; public abstract Task HandleAsync(); } diff --git a/Core/Stateflows/Activities/Classes/Flow.cs b/Core/Stateflows/Activities/Classes/Flow.cs index 3adc731b..c6a84422 100644 --- a/Core/Stateflows/Activities/Classes/Flow.cs +++ b/Core/Stateflows/Activities/Classes/Flow.cs @@ -1,13 +1,12 @@ using System.Threading.Tasks; -using Stateflows.Common; -using Stateflows.Common.Data; +using Stateflows.Activities.Context.Classes; using Stateflows.Activities.Context.Interfaces; namespace Stateflows.Activities { public abstract class BaseControlFlow { - public IFlowContext Context { get; internal set; } + public IActivityFlowContext Context => ActivityFlowContextAccessor.Context.Value; public virtual Task GuardAsync() => Task.FromResult(true); @@ -17,43 +16,26 @@ public abstract class ControlFlow : BaseControlFlow { } public abstract class BaseFlow : BaseControlFlow - where TToken : Token, new() { public virtual int Weight => 1; - new public IFlowContext Context - => (IFlowContext)base.Context; + new public IActivityFlowContext Context + => (IActivityFlowContext)base.Context; } public abstract class Flow : BaseFlow - where TToken : Token, new() - { } - - public abstract class DataFlow : Flow> { } public abstract class BaseTransformationFlow : BaseControlFlow - where TToken : Token, new() - where TTransformedToken : Token, new() { public virtual int Weight => 1; - new public IFlowContext Context - => (IFlowContext)base.Context; + new public IActivityFlowContext Context + => (IActivityFlowContext)base.Context; public abstract Task TransformAsync(); } public abstract class TransformationFlow : BaseTransformationFlow - where TToken : Token, new() - where TTransformedToken : Token, new() { } - - public abstract class DataTransformationFlow : TransformationFlow, Token> - { - public abstract Task TransformPayloadAsync(); - - public override async Task> TransformAsync() - => (await TransformPayloadAsync()).ToToken(); - } } diff --git a/Core/Stateflows/Activities/Classes/IterativeActivityNode.cs b/Core/Stateflows/Activities/Classes/IterativeActivityNode.cs index d56191d9..7bd26709 100644 --- a/Core/Stateflows/Activities/Classes/IterativeActivityNode.cs +++ b/Core/Stateflows/Activities/Classes/IterativeActivityNode.cs @@ -1,10 +1,8 @@ -using Stateflows.Common; -using Stateflows.Common.Extensions; +using Stateflows.Common.Extensions; namespace Stateflows.Activities { public abstract class IterativeActivityNode : StructuredActivityNode - where TToken : Token, new() { public static string Name => typeof(IterativeActivityNode).GetReadableName(); } diff --git a/Core/Stateflows/Activities/Classes/ParalellActivityNode.cs b/Core/Stateflows/Activities/Classes/ParalellActivityNode.cs index 6edcf377..1eb81ea2 100644 --- a/Core/Stateflows/Activities/Classes/ParalellActivityNode.cs +++ b/Core/Stateflows/Activities/Classes/ParalellActivityNode.cs @@ -1,10 +1,8 @@ -using Stateflows.Common; -using Stateflows.Common.Extensions; +using Stateflows.Common.Extensions; namespace Stateflows.Activities { public abstract class ParallelActivityNode : StructuredActivityNode - where TToken : Token, new() { public static string Name => typeof(ParallelActivityNode).GetReadableName(); } diff --git a/Core/Stateflows/Activities/Classes/StructuredActivityNode.cs b/Core/Stateflows/Activities/Classes/StructuredActivityNode.cs index aa4f4bdf..5ef4f84f 100644 --- a/Core/Stateflows/Activities/Classes/StructuredActivityNode.cs +++ b/Core/Stateflows/Activities/Classes/StructuredActivityNode.cs @@ -1,6 +1,5 @@ -using Stateflows.Activities.Context.Interfaces; -using Stateflows.Common; -using System.Threading.Tasks; +using System.Threading.Tasks; +using Stateflows.Activities.Context.Interfaces; namespace Stateflows.Activities { @@ -14,7 +13,6 @@ public virtual Task OnFinalizeAsync() } public abstract class StructuredActivityNode : StructuredActivityNode - where TToken : Token, new() { public new IActionContext Context => base.Context as IActionContext; } diff --git a/Core/Stateflows/Activities/Classes/TokensAccessor.cs b/Core/Stateflows/Activities/Classes/TokensAccessor.cs new file mode 100644 index 00000000..13b6e91e --- /dev/null +++ b/Core/Stateflows/Activities/Classes/TokensAccessor.cs @@ -0,0 +1,20 @@ +using Stateflows.Activities.Interfaces; +using System.Collections.Generic; + +namespace Stateflows.Activities +{ + public class TokensAccessor : ITokensAccessor + { + public List InputTokens + { + get => InputTokensHolder.Tokens.Value; + set => InputTokensHolder.Tokens.Value = value; + } + + public List OutputTokens + { + get => OutputTokensHolder.Tokens.Value; + set => OutputTokensHolder.Tokens.Value = value; + } + } +} diff --git a/Core/Stateflows/Activities/Collections/Input.cs b/Core/Stateflows/Activities/Collections/Input.cs index b3d9cddc..f2981aad 100644 --- a/Core/Stateflows/Activities/Collections/Input.cs +++ b/Core/Stateflows/Activities/Collections/Input.cs @@ -1,21 +1,21 @@ -using System.Linq; +using System; +using System.Linq; using System.Threading; using System.Collections; using System.Collections.Generic; -using Stateflows.Common; namespace Stateflows.Activities { - internal static class InputTokensHolder + public static class InputTokensHolder { - public static readonly AsyncLocal> Tokens = new AsyncLocal>(); + public static readonly AsyncLocal> Tokens = new AsyncLocal>(); } + [Serializable] public struct Input : IEnumerable - where TToken : Token, new() { private readonly IEnumerable Tokens - => InputTokensHolder.Tokens.Value.OfType(); + => InputTokensHolder.Tokens.Value.OfType>().Select(t => t.Payload); public readonly IEnumerator GetEnumerator() => Tokens.GetEnumerator(); @@ -27,21 +27,21 @@ public readonly void PassAllOn() => new Output().AddRange(Tokens); } + [Serializable] public struct SingleInput - where TToken : Token, new() { public readonly TToken Token - => InputTokensHolder.Tokens.Value.OfType().First(); + => InputTokensHolder.Tokens.Value.OfType>().Select(t => t.Payload).First(); public readonly void PassOn() => new Output().Add(Token); } + [Serializable] public struct OptionalInput : IEnumerable - where TToken : Token, new() { private readonly IEnumerable Tokens - => InputTokensHolder.Tokens.Value.OfType(); + => InputTokensHolder.Tokens.Value.OfType>().Select(t => t.Payload); public readonly IEnumerator GetEnumerator() => Tokens.GetEnumerator(); @@ -53,11 +53,11 @@ public readonly void PassAllOn() => new Output().AddRange(Tokens); } + [Serializable] public struct OptionalSingleInput - where TToken : Token, new() { public readonly TToken Token - => InputTokensHolder.Tokens.Value.OfType().First(); + => InputTokensHolder.Tokens.Value.OfType>().Select(t => t.Payload).First(); public readonly void PassOn() => new Output().Add(Token); diff --git a/Core/Stateflows/Activities/Collections/Output.cs b/Core/Stateflows/Activities/Collections/Output.cs index 68a5f155..6061bbfc 100644 --- a/Core/Stateflows/Activities/Collections/Output.cs +++ b/Core/Stateflows/Activities/Collections/Output.cs @@ -2,33 +2,32 @@ using System.Threading; using System.Collections; using System.Collections.Generic; -using Stateflows.Common; +using Stateflows.Utils; namespace Stateflows.Activities { - internal static class OutputTokensHolder + public static class OutputTokensHolder { - public static readonly AsyncLocal> Tokens = new AsyncLocal>(); + public static readonly AsyncLocal> Tokens = new AsyncLocal>(); } public struct Output : ICollection - where TToken : Token, new() { private readonly List GetTokens() - => OutputTokensHolder.Tokens.Value.OfType().ToList(); + => OutputTokensHolder.Tokens.Value.OfType>().FromTokens().ToList(); public readonly int Count => GetTokens().Count; public readonly bool IsReadOnly => false; public readonly void Add(TToken item) - => OutputTokensHolder.Tokens.Value.Add(item); + => OutputTokensHolder.Tokens.Value.Add(item.ToTokenHolder()); public readonly void AddRange(IEnumerable items) { foreach (var item in items) { - OutputTokensHolder.Tokens.Value.Add(item); + OutputTokensHolder.Tokens.Value.Add(item.ToTokenHolder()); } } @@ -36,13 +35,13 @@ public readonly void Clear() => OutputTokensHolder.Tokens.Value.RemoveAll(token => token is TToken); public readonly bool Contains(TToken item) - => OutputTokensHolder.Tokens.Value.Contains(item); + => OutputTokensHolder.Tokens.Value.Contains(item.ToTokenHolder()); public readonly void CopyTo(TToken[] array, int arrayIndex) - => OutputTokensHolder.Tokens.Value.CopyTo(array, arrayIndex); + => OutputTokensHolder.Tokens.Value.CopyTo(array.ToTokens().ToArray(), arrayIndex); public readonly bool Remove(TToken item) - => OutputTokensHolder.Tokens.Value.Remove(item); + => OutputTokensHolder.Tokens.Value.Remove(item.ToTokenHolder()); public readonly IEnumerator GetEnumerator() => GetTokens().GetEnumerator(); diff --git a/Core/Stateflows/Activities/Context/Classes/AcceptEventActionContext.cs b/Core/Stateflows/Activities/Context/Classes/AcceptEventActionContext.cs index 231e1c3f..5947ac70 100644 --- a/Core/Stateflows/Activities/Context/Classes/AcceptEventActionContext.cs +++ b/Core/Stateflows/Activities/Context/Classes/AcceptEventActionContext.cs @@ -21,29 +21,21 @@ public AcceptEventActionContext(ActionContext actionContext) public INodeContext CurrentNode => ActionContext.CurrentNode; - public IEnumerable Input => ActionContext.InputTokens; + public IEnumerable Input => ActionContext.InputTokens; public void Output(TToken token) - where TToken : Token, new() => ActionContext.Output(token); public void OutputRange(IEnumerable tokens) - where TToken : Token, new() => ActionContext.OutputRange(tokens); - public void OutputRangeAsGroup(IEnumerable tokens) - where TToken : Token, new() - => ActionContext.OutputRangeAsGroup(tokens); - public void PassTokensOfTypeOn() - where TToken : Token, new() => ActionContext.PassTokensOfTypeOn(); - public void PassTokensOfTypeOnAsGroup() - where TToken : Token, new() - => ActionContext.PassTokensOfTypeOnAsGroup(); + public void PassAllTokensOn() + => ActionContext.PassAllTokensOn(); - public void PassAllOn() - => ActionContext.PassAllOn(); + public IEnumerable GetTokensOfType() + => ActionContext.GetTokensOfType(); } } diff --git a/Core/Stateflows/Activities/Context/Classes/ActionContext.cs b/Core/Stateflows/Activities/Context/Classes/ActionContext.cs index cddbb3e9..17e21630 100644 --- a/Core/Stateflows/Activities/Context/Classes/ActionContext.cs +++ b/Core/Stateflows/Activities/Context/Classes/ActionContext.cs @@ -1,6 +1,7 @@ using System.Linq; using System.Collections.Generic; using Stateflows.Common; +using Stateflows.Utils; using Stateflows.Activities.Models; using Stateflows.Activities.Engine; using Stateflows.Activities.Context.Interfaces; @@ -8,23 +9,9 @@ namespace Stateflows.Activities.Context.Classes { - internal class ActionContext : ActivityNodeContext, IActionContext, IActivityNodeInspectionContext + internal class ActionContext : ActivityNodeContext, IActionContext, IActivityNodeInspectionContext { - public ActionContext(BaseContext context, Node node, IEnumerable inputTokens = null, IEnumerable selectionTokens = null) - : base(context, node) - { - if (inputTokens != null) - { - InputTokens.AddRange(inputTokens); - } - - if (selectionTokens != null) - { - Tokens = selectionTokens; - } - } - - public ActionContext(RootContext context, NodeScope nodeScope, Node node, IEnumerable inputTokens, IEnumerable selectionTokens = null) + public ActionContext(RootContext context, NodeScope nodeScope, Node node, IEnumerable inputTokens, IEnumerable selectionTokens = null) : base(context, nodeScope, node) { InputTokens.AddRange(inputTokens); @@ -35,37 +22,28 @@ public ActionContext(RootContext context, NodeScope nodeScope, Node node, IEnume } } - public List InputTokens { get; } = new List(); + public List InputTokens { get; } = new List(); - public List OutputTokens { get; } = new List(); + public List OutputTokens { get; } = new List(); public void Output(TToken token) - where TToken : Token, new() => OutputRange(new TToken[] { token }); public void OutputRange(IEnumerable tokens) - where TToken : Token, new() - { - OutputTokens.AddRange(tokens); - } - - public void OutputRangeAsGroup(IEnumerable tokens) - where TToken : Token, new() - => Output(tokens.ToGroupToken()); + => OutputTokens.AddRange(tokens.ToTokens()); public void PassTokensOfTypeOn() - where TToken : Token, new() - => OutputRange(InputTokens.OfType()); + => OutputTokens.AddRange(InputTokens.OfType>()); - public void PassTokensOfTypeOnAsGroup() - where TToken : Token, new() - => Output(InputTokens.OfType().ToGroupToken()); + public void PassAllTokensOn() + => OutputTokens.AddRange(InputTokens); - public void PassAllOn() - => OutputRange(InputTokens); + public IEnumerable GetTokensOfType() + => InputTokens.OfType>().FromTokens().ToArray(); - public IEnumerable Input => InputTokens; + public IEnumerable GetAllTokens() + => InputTokens.FromTokens().ToArray(); - public IEnumerable Tokens { get; } + public IEnumerable Tokens { get; } } } \ No newline at end of file diff --git a/Core/Stateflows/Activities/Context/Classes/ActivityFlowContextAccessor.cs b/Core/Stateflows/Activities/Context/Classes/ActivityFlowContextAccessor.cs new file mode 100644 index 00000000..a3797e3b --- /dev/null +++ b/Core/Stateflows/Activities/Context/Classes/ActivityFlowContextAccessor.cs @@ -0,0 +1,10 @@ +using System.Threading; +using Stateflows.Activities.Context.Interfaces; + +namespace Stateflows.Activities.Context.Classes +{ + public static class ActivityFlowContextAccessor + { + public static readonly AsyncLocal Context = new AsyncLocal(); + } +} diff --git a/Core/Stateflows/Activities/Context/Classes/ActivityNodeContext.cs b/Core/Stateflows/Activities/Context/Classes/ActivityNodeContext.cs index 25b53e40..6f8f418c 100644 --- a/Core/Stateflows/Activities/Context/Classes/ActivityNodeContext.cs +++ b/Core/Stateflows/Activities/Context/Classes/ActivityNodeContext.cs @@ -27,6 +27,6 @@ public ActivityNodeContext(RootContext context, NodeScope nodeScope, Node node) private INodeContext currentNode = null; public INodeContext CurrentNode - => currentNode ??= new NodeContext(Node, Context); + => currentNode ??= new NodeContext(Node, Context, NodeScope); } } diff --git a/Core/Stateflows/Activities/Context/Classes/ActivityNodeContextAccessor.cs b/Core/Stateflows/Activities/Context/Classes/ActivityNodeContextAccessor.cs new file mode 100644 index 00000000..3c2810ec --- /dev/null +++ b/Core/Stateflows/Activities/Context/Classes/ActivityNodeContextAccessor.cs @@ -0,0 +1,10 @@ +using System.Threading; +using Stateflows.Activities.Context.Interfaces; + +namespace Stateflows.Activities.Context.Classes +{ + public static class ActivityNodeContextAccessor + { + public static readonly AsyncLocal Context = new AsyncLocal(); + } +} diff --git a/Core/Stateflows/Activities/Context/Classes/EventContext.cs b/Core/Stateflows/Activities/Context/Classes/EventContext.cs index 8f64a6c3..c4c1add5 100644 --- a/Core/Stateflows/Activities/Context/Classes/EventContext.cs +++ b/Core/Stateflows/Activities/Context/Classes/EventContext.cs @@ -2,13 +2,11 @@ using Stateflows.Activities.Engine; using Stateflows.Activities.Context.Interfaces; using Stateflows.Activities.Inspection.Interfaces; -using Stateflows.Common.Interfaces; -using Stateflows.Common.Context; namespace Stateflows.Activities.Context.Classes { internal class EventContext : BaseContext, IEventInspectionContext, IRootContext - where TEvent : Event + where TEvent : Event, new() { IActivityContext IActivityActionContext.Activity => Activity; diff --git a/Core/Stateflows/Activities/Context/Classes/ExceptionHandlerContext.cs b/Core/Stateflows/Activities/Context/Classes/ExceptionHandlerContext.cs index 5d7a7ca8..5fd5f12e 100644 --- a/Core/Stateflows/Activities/Context/Classes/ExceptionHandlerContext.cs +++ b/Core/Stateflows/Activities/Context/Classes/ExceptionHandlerContext.cs @@ -1,9 +1,8 @@ using System; using System.Linq; -using System.Collections.Generic; using Stateflows.Activities.Models; -using Stateflows.Activities.Engine; using Stateflows.Activities.Context.Interfaces; +using Stateflows.Activities.Engine; namespace Stateflows.Activities.Context.Classes { @@ -14,14 +13,26 @@ internal class ExceptionHandlerContext : ActionContext, IExceptionHa public TException exception = null; public TException Exception - => exception ??= InputTokens.OfType>().First(t => t.Exception is TException).Exception as TException; + { + get + { + exception ??= + InputTokens.OfType>().FirstOrDefault()?.TypedException ?? + InputTokens.OfType().FirstOrDefault()?.Exception as TException; + + return exception; + } + } + + public INodeContext ProtectedNode { get; set; } public INodeContext NodeOfOrigin { get; set; } - public ExceptionHandlerContext(ActionContext context, Node nodeOfOrigin) + public ExceptionHandlerContext(ActionContext context, Node protectedNode, Node nodeOfOrigin, NodeScope nodeScope) : base(context.Context, context.NodeScope, context.Node, context.InputTokens) { - NodeOfOrigin = new NodeContext(nodeOfOrigin, context.Context); + ProtectedNode = new NodeContext(protectedNode, context.Context, nodeScope); + NodeOfOrigin = new NodeContext(nodeOfOrigin, context.Context, nodeScope); } } } diff --git a/Core/Stateflows/Activities/Context/Classes/FlowContext.cs b/Core/Stateflows/Activities/Context/Classes/FlowContext.cs new file mode 100644 index 00000000..7c9cde0b --- /dev/null +++ b/Core/Stateflows/Activities/Context/Classes/FlowContext.cs @@ -0,0 +1,48 @@ +using System; +using Stateflows.Activities.Models; +using Stateflows.Activities.Streams; +using Stateflows.Activities.Context.Interfaces; +using Stateflows.Activities.Engine; + +namespace Stateflows.Activities.Context.Classes +{ + internal class FlowContext : BaseContext, + IActivityFlowContext, + IIncomingFlowContext, + IRootContext + { + IActivityContext IActivityActionContext.Activity => Activity; + + protected readonly Edge edge; + + private readonly TokenPipelineContext context; + + private Stream stream; + protected Stream Stream => stream ??= Context.GetStream(edge.Identifier, NodeScope.ThreadId); + + public FlowContext(TokenPipelineContext context) + : base(context) + { + this.context = context; + edge = context.Edge; + } + + public FlowContext(RootContext context, NodeScope nodeScope, Edge edge) + : base(context, nodeScope) + { + this.edge = edge; + } + + public ISourceNodeContext SourceNode => context.SourceNode; + + public INodeContext TargetNode => context.TargetNode; + + public Type TokenType => edge.TokenType; + + public int Weight => edge.Weight; + + public int TokenCount => Stream.Tokens.Count; + + public bool Activated => Stream.IsActivated; + } +} diff --git a/Core/Stateflows/Activities/Context/Classes/NodeContext.cs b/Core/Stateflows/Activities/Context/Classes/NodeContext.cs index 9ed5220b..f483ac88 100644 --- a/Core/Stateflows/Activities/Context/Classes/NodeContext.cs +++ b/Core/Stateflows/Activities/Context/Classes/NodeContext.cs @@ -1,5 +1,8 @@ -using Stateflows.Activities.Models; +using System.Linq; +using System.Collections.Generic; +using Stateflows.Activities.Models; using Stateflows.Activities.Context.Interfaces; +using Stateflows.Activities.Engine; namespace Stateflows.Activities.Context.Classes { @@ -13,10 +16,21 @@ internal class NodeContext : INodeContext internal RootContext Context { get; } - public NodeContext(Node node, RootContext context) + internal NodeScope NodeScope { get; } + + private IEnumerable incomingFlows; + public IEnumerable IncomingFlows + => incomingFlows ??= Node.IncomingEdges.Select(edge => new FlowContext(Context, NodeScope, edge)); + + private IEnumerable outgoingFlows; + public IEnumerable OutgoingFlows + => outgoingFlows ??= Node.Edges.Select(edge => new FlowContext(Context, NodeScope, edge)); + + public NodeContext(Node node, RootContext context, NodeScope nodeScope) { Node = node; Context = context; + NodeScope = nodeScope; } public bool TryGetParentNode(out INodeContext parentNodeContext) @@ -24,7 +38,7 @@ public bool TryGetParentNode(out INodeContext parentNodeContext) var parent = Node.Parent; parentNodeContext = parent != null - ? new NodeContext(parent, Context) + ? new NodeContext(parent, Context, null) : null; return parentNodeContext != null; diff --git a/Core/Stateflows/Activities/Context/Classes/RootContext.cs b/Core/Stateflows/Activities/Context/Classes/RootContext.cs index f5909269..2ba8acb6 100644 --- a/Core/Stateflows/Activities/Context/Classes/RootContext.cs +++ b/Core/Stateflows/Activities/Context/Classes/RootContext.cs @@ -11,7 +11,6 @@ using Stateflows.Activities.Engine; using Stateflows.Activities.Streams; using Stateflows.Activities.Registration; -using System.Xml.Linq; namespace Stateflows.Activities.Context.Classes { @@ -119,8 +118,8 @@ public void ClearStream(string edgeIdentifier, Guid threadId) } } - private Dictionary>> outputTokens = null; - public Dictionary>> OutputTokens + private Dictionary>> outputTokens = null; + public Dictionary>> OutputTokens { get { @@ -130,12 +129,12 @@ public Dictionary>> OutputTokens { if (!Context.Values.TryGetValue(Constants.OutputTokens, out var outputTokensObj)) { - outputTokens = new Dictionary>>(); + outputTokens = new Dictionary>>(); Context.Values[Constants.OutputTokens] = outputTokens; } else { - outputTokens = outputTokensObj as Dictionary>>; + outputTokens = outputTokensObj as Dictionary>>; } } } @@ -144,21 +143,21 @@ public Dictionary>> OutputTokens } } - public List GetOutputTokens(string nodeName, Guid threadId) + public List GetOutputTokens(string nodeName, Guid threadId) { - List tokens; + List tokens; lock (OutputTokens) { if (!OutputTokens.TryGetValue(threadId, out var nodes)) { - nodes = new Dictionary>(); + nodes = new Dictionary>(); OutputTokens[threadId] = nodes; } if (!nodes.TryGetValue(nodeName, out tokens)) { - tokens = new List(); + tokens = new List(); nodes[nodeName] = tokens; } } @@ -319,7 +318,6 @@ internal bool IsNodeCompleted(Node node, NodeScope nodeScope) => nodeScope.IsTerminated || (nodeScope.ChildScope?.IsTerminated ?? false) || ( - !GetStreams(nodeScope.ThreadId).Values.Any(s => s.Tokens.Any()) && !node.Nodes.Values.Any(node => node.Type == NodeType.AcceptEventAction && !node.IncomingEdges.Any()) && !ActiveNodes.Any() ); diff --git a/Core/Stateflows/Activities/Context/Classes/SourceNodeContext.cs b/Core/Stateflows/Activities/Context/Classes/SourceNodeContext.cs index 0d2359ad..7cc97493 100644 --- a/Core/Stateflows/Activities/Context/Classes/SourceNodeContext.cs +++ b/Core/Stateflows/Activities/Context/Classes/SourceNodeContext.cs @@ -3,7 +3,8 @@ using System.Collections.Generic; using Stateflows.Activities.Models; using Stateflows.Activities.Context.Interfaces; -using Stateflows.Common; +using Stateflows.Utils; +using Stateflows.Activities.Engine; namespace Stateflows.Activities.Context.Classes { @@ -11,19 +12,18 @@ internal class SourceNodeContext : NodeContext, ISourceNodeContext { internal readonly Guid ThreadId; - private IEnumerable input = null; - public IEnumerable Input -#pragma warning disable S2365 // Properties should not make collection or array copies - => input ??= Context + public SourceNodeContext(Node node, RootContext context, NodeScope nodeScope) + : base(node, context, nodeScope) + { + ThreadId = nodeScope.ThreadId; + } + + public IEnumerable GetTokensOfType() + => Context .GetActivatedStreams(Node, ThreadId) .SelectMany(stream => stream.Tokens) + .OfType>() + .FromTokens() .ToArray(); -#pragma warning restore S2365 // Properties should not make collection or array copies - - public SourceNodeContext(Node node, RootContext context, Guid threadId) - : base(node, context) - { - ThreadId = threadId; - } } } diff --git a/Core/Stateflows/Activities/Context/Classes/TokenFlowContext.cs b/Core/Stateflows/Activities/Context/Classes/TokenFlowContext.cs index 650562e6..aba40709 100644 --- a/Core/Stateflows/Activities/Context/Classes/TokenFlowContext.cs +++ b/Core/Stateflows/Activities/Context/Classes/TokenFlowContext.cs @@ -1,34 +1,20 @@ -using Stateflows.Activities.Models; -using Stateflows.Activities.Context.Interfaces; -using Stateflows.Common; +using Stateflows.Activities.Context.Interfaces; namespace Stateflows.Activities.Context.Classes { - internal class TokenFlowContext : BaseContext, + internal class TokenFlowContext : FlowContext, IGuardContext, ITransformationContext, IRootContext - where TToken : Token, new() { IActivityContext IActivityActionContext.Activity => Activity; - private readonly Edge Edge; - public TokenFlowContext(TokenPipelineContext context, TToken token) : base(context) { - Edge = context.Edge; Token = token; } public TToken Token { get; private set; } - - public ISourceNodeContext sourceNode = null; - public ISourceNodeContext SourceNode - => sourceNode ??= new SourceNodeContext(Edge.Source, Context, NodeScope.ThreadId); - - private INodeContext targetNode = null; - public INodeContext TargetNode - => targetNode ??= new NodeContext(Edge.Target, Context); } } diff --git a/Core/Stateflows/Activities/Context/Classes/TokenPipelineContext.cs b/Core/Stateflows/Activities/Context/Classes/TokenPipelineContext.cs index 917a4728..44a3aaae 100644 --- a/Core/Stateflows/Activities/Context/Classes/TokenPipelineContext.cs +++ b/Core/Stateflows/Activities/Context/Classes/TokenPipelineContext.cs @@ -1,13 +1,12 @@ using Stateflows.Activities.Models; using Stateflows.Activities.Engine; using Stateflows.Activities.Context.Interfaces; -using Stateflows.Common; namespace Stateflows.Activities.Context.Classes { internal class TokenPipelineContext : BaseContext, IRootContext { - public TokenPipelineContext(BaseContext context, Edge edge, Token token) + public TokenPipelineContext(BaseContext context, Edge edge, TokenHolder token) : base(context) { Edge = edge; @@ -16,16 +15,16 @@ public TokenPipelineContext(BaseContext context, Edge edge, Token token) internal readonly Edge Edge; - public readonly Token Token; + public readonly TokenHolder Token; public bool TokenConsumed = false; public ISourceNodeContext sourceNode = null; public ISourceNodeContext SourceNode - => sourceNode ??= new SourceNodeContext(Edge.Source, Context, NodeScope.ThreadId); + => sourceNode ??= new SourceNodeContext(Edge.Source, Context, NodeScope); public INodeContext targetNode = null; public INodeContext TargetNode - => targetNode ??= new NodeContext(Edge.Target, Context); + => targetNode ??= new NodeContext(Edge.Target, Context, NodeScope); } } diff --git a/Core/Stateflows/Activities/Context/Interfaces/IAcceptEventActionContext.cs b/Core/Stateflows/Activities/Context/Interfaces/IAcceptEventActionContext.cs index 3136ef40..ac4f6c8f 100644 --- a/Core/Stateflows/Activities/Context/Interfaces/IAcceptEventActionContext.cs +++ b/Core/Stateflows/Activities/Context/Interfaces/IAcceptEventActionContext.cs @@ -3,7 +3,7 @@ namespace Stateflows.Activities.Context.Interfaces { public interface IAcceptEventActionContext : IActionContext - where TEvent : Event + where TEvent : Event, new() { TEvent Event { get; } } diff --git a/Core/Stateflows/Activities/Context/Interfaces/IActionContext.cs b/Core/Stateflows/Activities/Context/Interfaces/IActionContext.cs index 851203c7..9069601f 100644 --- a/Core/Stateflows/Activities/Context/Interfaces/IActionContext.cs +++ b/Core/Stateflows/Activities/Context/Interfaces/IActionContext.cs @@ -1,6 +1,4 @@ -using Stateflows.Common; - -namespace Stateflows.Activities.Context.Interfaces +namespace Stateflows.Activities.Context.Interfaces { public interface ITypedActionContext : IActivityNodeContext { } @@ -9,6 +7,5 @@ public interface IActionContext : ITypedActionContext, IInput, IOutput { } public interface IActionContext : IActionContext, ITokenContext - where TToken : Token, new() { } } diff --git a/Core/Stateflows/Activities/Context/Interfaces/IActivityActionContext.cs b/Core/Stateflows/Activities/Context/Interfaces/IActivityActionContext.cs index cc15cb6d..161ab4d3 100644 --- a/Core/Stateflows/Activities/Context/Interfaces/IActivityActionContext.cs +++ b/Core/Stateflows/Activities/Context/Interfaces/IActivityActionContext.cs @@ -4,6 +4,9 @@ namespace Stateflows.Activities.Context.Interfaces { public interface IActivityActionContext : IBehaviorLocator { + /// + /// Information about activity + /// IActivityContext Activity { get; } } } diff --git a/Core/Stateflows/Activities/Context/Interfaces/IActivityContext.cs b/Core/Stateflows/Activities/Context/Interfaces/IActivityContext.cs index 33d2a42d..e0605e3d 100644 --- a/Core/Stateflows/Activities/Context/Interfaces/IActivityContext.cs +++ b/Core/Stateflows/Activities/Context/Interfaces/IActivityContext.cs @@ -4,8 +4,14 @@ namespace Stateflows.Activities.Context.Interfaces { public interface IActivityContext : IBehaviorContext { + /// + /// Identifier of current Activity behavior + /// new ActivityId Id { get; } + /// + /// Behavior-level lock handle enabling developer to synchronize operations between Activity's nodes + /// object LockHandle { get; } } } diff --git a/Core/Stateflows/Activities/Context/Interfaces/IActivityFlowContext.cs b/Core/Stateflows/Activities/Context/Interfaces/IActivityFlowContext.cs new file mode 100644 index 00000000..bb2247b6 --- /dev/null +++ b/Core/Stateflows/Activities/Context/Interfaces/IActivityFlowContext.cs @@ -0,0 +1,33 @@ +using System; + +namespace Stateflows.Activities.Context.Interfaces +{ + public interface IFlowContext + { + ISourceNodeContext SourceNode { get; } + + INodeContext TargetNode { get; } + + Type TokenType { get; } + + int Weight { get; } + } + + public interface IIncomingFlowContext : IFlowContext + { + bool Activated { get; } + + int TokenCount { get; } + } + + public interface IFlowTokenContext + { + TToken Token { get; } + } + + public interface IActivityFlowContext : IActivityActionContext, IFlowContext + { } + + public interface IActivityFlowContext : IActivityFlowContext, IFlowTokenContext + { } +} diff --git a/Core/Stateflows/Activities/Context/Interfaces/IActivityNodeContext.cs b/Core/Stateflows/Activities/Context/Interfaces/IActivityNodeContext.cs index 8814aa82..3a9781f2 100644 --- a/Core/Stateflows/Activities/Context/Interfaces/IActivityNodeContext.cs +++ b/Core/Stateflows/Activities/Context/Interfaces/IActivityNodeContext.cs @@ -4,8 +4,14 @@ namespace Stateflows.Activities.Context.Interfaces { public interface IActivityNodeContext : IActivityActionContext { + /// + /// Information about current node + /// INodeContext CurrentNode { get; } + /// + /// Cancellation token handling activity execution interruptions, f.e. triggered by FinalNode + /// CancellationToken CancellationToken { get; } } } diff --git a/Core/Stateflows/Activities/Context/Interfaces/IEventContext.cs b/Core/Stateflows/Activities/Context/Interfaces/IEventContext.cs index 74087cb1..af5a17ea 100644 --- a/Core/Stateflows/Activities/Context/Interfaces/IEventContext.cs +++ b/Core/Stateflows/Activities/Context/Interfaces/IEventContext.cs @@ -3,7 +3,7 @@ namespace Stateflows.Activities.Context.Interfaces { public interface IEventContext : IActivityActionContext - where TEvent : Event + where TEvent : Event, new() { TEvent Event { get; } } diff --git a/Core/Stateflows/Activities/Context/Interfaces/IExceptionHandlerContext.cs b/Core/Stateflows/Activities/Context/Interfaces/IExceptionHandlerContext.cs index e35e1cb0..0317d019 100644 --- a/Core/Stateflows/Activities/Context/Interfaces/IExceptionHandlerContext.cs +++ b/Core/Stateflows/Activities/Context/Interfaces/IExceptionHandlerContext.cs @@ -7,6 +7,8 @@ public interface IExceptionHandlerContext : IActivityNodeContext { TException Exception { get; } + INodeContext ProtectedNode { get; } + INodeContext NodeOfOrigin { get; } } } diff --git a/Core/Stateflows/Activities/Context/Interfaces/IFlowContext.cs b/Core/Stateflows/Activities/Context/Interfaces/IFlowContext.cs deleted file mode 100644 index d6cf0003..00000000 --- a/Core/Stateflows/Activities/Context/Interfaces/IFlowContext.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Stateflows.Common; - -namespace Stateflows.Activities.Context.Interfaces -{ - public interface IFlowContext : IActivityActionContext - { - ISourceNodeContext SourceNode { get; } - - INodeContext TargetNode { get; } - } - - public interface IFlowContext : IFlowContext - where TToken : Token, new() - { - TToken Token { get; } - } -} diff --git a/Core/Stateflows/Activities/Context/Interfaces/IGuardContext.cs b/Core/Stateflows/Activities/Context/Interfaces/IGuardContext.cs index cf13d599..03991289 100644 --- a/Core/Stateflows/Activities/Context/Interfaces/IGuardContext.cs +++ b/Core/Stateflows/Activities/Context/Interfaces/IGuardContext.cs @@ -1,11 +1,8 @@ -using Stateflows.Common; - -namespace Stateflows.Activities.Context.Interfaces +namespace Stateflows.Activities.Context.Interfaces { - public interface IGuardContext : IFlowContext + public interface IGuardContext : IActivityFlowContext { } - public interface IGuardContext : IFlowContext - where TToken : Token, new() + public interface IGuardContext : IActivityFlowContext { } } diff --git a/Core/Stateflows/Activities/Context/Interfaces/IInput.cs b/Core/Stateflows/Activities/Context/Interfaces/IInput.cs index 6b4a1cae..531ba127 100644 --- a/Core/Stateflows/Activities/Context/Interfaces/IInput.cs +++ b/Core/Stateflows/Activities/Context/Interfaces/IInput.cs @@ -1,10 +1,9 @@ using System.Collections.Generic; -using Stateflows.Common; namespace Stateflows.Activities.Context.Interfaces { public interface IInput { - IEnumerable Input { get; } + IEnumerable GetTokensOfType(); } } diff --git a/Core/Stateflows/Activities/Context/Interfaces/INodeContext.cs b/Core/Stateflows/Activities/Context/Interfaces/INodeContext.cs index 854c82f8..d47becbb 100644 --- a/Core/Stateflows/Activities/Context/Interfaces/INodeContext.cs +++ b/Core/Stateflows/Activities/Context/Interfaces/INodeContext.cs @@ -1,11 +1,34 @@ -namespace Stateflows.Activities.Context.Interfaces +using System.Collections.Generic; + +namespace Stateflows.Activities.Context.Interfaces { public interface INodeContext { + /// + /// Name of the node + /// string NodeName { get; } + /// + /// Type of the node + /// NodeType NodeType { get; } + /// + /// Collection of flows incoming to the node + /// + IEnumerable IncomingFlows { get; } + + /// + /// Collection of flows outgoing from the node + /// + IEnumerable OutgoingFlows { get; } + + /// + /// Provides access to parent node (if available) + /// + /// out parameter with reference to parent node information + /// True when parent node is available, false otherwise bool TryGetParentNode(out INodeContext parentNodeContext); } } diff --git a/Core/Stateflows/Activities/Context/Interfaces/IOutput.cs b/Core/Stateflows/Activities/Context/Interfaces/IOutput.cs index 7672a78b..9ff1ebba 100644 --- a/Core/Stateflows/Activities/Context/Interfaces/IOutput.cs +++ b/Core/Stateflows/Activities/Context/Interfaces/IOutput.cs @@ -1,25 +1,15 @@ using System.Collections.Generic; -using Stateflows.Common; namespace Stateflows.Activities.Context.Interfaces { public interface IOutput { - void Output(TToken token) - where TToken : Token, new(); + void Output(TToken token); - void OutputRange(IEnumerable tokens) - where TToken : Token, new(); + void OutputRange(IEnumerable tokens); - void OutputRangeAsGroup(IEnumerable tokens) - where TToken : Token, new(); + void PassTokensOfTypeOn(); - void PassTokensOfTypeOn() - where TToken : Token, new(); - - void PassTokensOfTypeOnAsGroup() - where TToken : Token, new(); - - void PassAllOn(); + void PassAllTokensOn(); } } diff --git a/Core/Stateflows/Activities/Context/Interfaces/IPipelineContext.cs b/Core/Stateflows/Activities/Context/Interfaces/IPipelineContext.cs index e1945501..f5ac3bdf 100644 --- a/Core/Stateflows/Activities/Context/Interfaces/IPipelineContext.cs +++ b/Core/Stateflows/Activities/Context/Interfaces/IPipelineContext.cs @@ -1,10 +1,9 @@ using System.Collections.Generic; -using Stateflows.Common; namespace Stateflows.Activities.Context.Interfaces { - public interface IPipelineContext : IFlowContext + public interface IPipelineContext : IActivityFlowContext { - IEnumerable Tokens { get; } + IEnumerable Tokens { get; } } } diff --git a/Core/Stateflows/Activities/Context/Interfaces/ITokenContext.cs b/Core/Stateflows/Activities/Context/Interfaces/ITokenContext.cs index 5c0702ba..688fff34 100644 --- a/Core/Stateflows/Activities/Context/Interfaces/ITokenContext.cs +++ b/Core/Stateflows/Activities/Context/Interfaces/ITokenContext.cs @@ -1,10 +1,8 @@ -using Stateflows.Common; -using System.Collections.Generic; +using System.Collections.Generic; namespace Stateflows.Activities.Context.Interfaces { public interface ITokenContext : IActivityActionContext - where TToken : Token, new() { IEnumerable Tokens { get; } } diff --git a/Core/Stateflows/Activities/Context/Interfaces/ITransformationContext.cs b/Core/Stateflows/Activities/Context/Interfaces/ITransformationContext.cs index 47f47c3c..89785f83 100644 --- a/Core/Stateflows/Activities/Context/Interfaces/ITransformationContext.cs +++ b/Core/Stateflows/Activities/Context/Interfaces/ITransformationContext.cs @@ -1,8 +1,5 @@ -using Stateflows.Common; - -namespace Stateflows.Activities.Context.Interfaces +namespace Stateflows.Activities.Context.Interfaces { public interface ITransformationContext : IGuardContext - where TToken : Token, new() { } } diff --git a/Core/Stateflows/Activities/Engine/Executor.cs b/Core/Stateflows/Activities/Engine/Executor.cs index 8fdfecb7..ecdfb718 100644 --- a/Core/Stateflows/Activities/Engine/Executor.cs +++ b/Core/Stateflows/Activities/Engine/Executor.cs @@ -6,19 +6,20 @@ using System.Collections.Generic; using Microsoft.Extensions.Logging; using Microsoft.Extensions.DependencyInjection; +using Stateflows.Utils; using Stateflows.Common; using Stateflows.Common.Utilities; using Stateflows.Activities.Models; using Stateflows.Activities.Streams; using Stateflows.Activities.Registration; using Stateflows.Activities.Context.Classes; -using Stateflows.Utils; -using Stateflows.Common.Data; namespace Stateflows.Activities.Engine { internal class Executor : IDisposable { + private static readonly object lockHandle = new object(); + public readonly Graph Graph; public readonly ActivitiesRegister Register; public readonly NodeScope NodeScope; @@ -128,14 +129,15 @@ public async Task InitializeAsync(InitializationRequest @event) { Context.Initialized = true; - //Context.ClearEvent(); - await ExecuteGraphAsync(); return true; } - Logger.LogInformation("Behavior \"{id}\" is already initialized.", $"{Context.Id.BehaviorId.Type}:{Context.Id.Name}:{Context.Id.Instance}"); + if (Initialized) + { + Logger.LogInformation("Behavior \"{id}\" is already initialized.", $"{Context.Id.BehaviorId.Type}:{Context.Id.Name}:{Context.Id.Instance}"); + } return false; } @@ -177,9 +179,9 @@ public void Reset(bool keepVersion) } } - private IEnumerable OutputTokens { get; set; } = null; + private IEnumerable OutputTokens { get; set; } = null; - public async Task> GetResultAsync() + public async Task> GetResultAsync() { await FinalizationEvent.WaitOneAsync(); @@ -187,7 +189,7 @@ public async Task> GetResultAsync() } public async Task ProcessAsync(TEvent @event) - where TEvent : Event + where TEvent : Event, new() { var result = EventStatus.Rejected; @@ -202,7 +204,7 @@ public async Task ProcessAsync(TEvent @event) } private async Task DoProcessAsync(TEvent @event) - where TEvent : Event + where TEvent : Event, new() { Debug.Assert(Context != null, $"Context is not available. Is activity '{Graph.Name}' hydrated?"); @@ -210,10 +212,10 @@ private async Task DoProcessAsync(TEvent @event) var activeNode = activeNodes.FirstOrDefault(node => node.EventType == @event.GetType() && ( - !(@event is TimeEvent) || + !(@event is TimeEvent timeEvent) || ( Context.NodeTimeEvents.TryGetValue(node.Identifier, out var timeEventId) && - @event.Id == timeEventId + timeEvent.Id == timeEventId ) ) ); @@ -245,7 +247,7 @@ private async Task ExecuteGraphAsync() return EventStatus.Consumed; } - public async Task DoFinalizeAsync(IEnumerable outputTokens = null) + public async Task DoFinalizeAsync(IEnumerable outputTokens = null) { if (Finalized) return; @@ -267,7 +269,7 @@ public async Task DoFinalizeAsync(IEnumerable outputTokens = null) FinalizationEvent.Set(); } - public async Task<(IEnumerable Output, bool Finalized)> DoExecuteStructuredNodeAsync(Node node, NodeScope nodeScope, IEnumerable input = null) + public async Task<(IEnumerable Output, bool Finalized)> DoExecuteStructuredNodeAsync(Node node, NodeScope nodeScope, IEnumerable input = null) { if (node.Anchored) { @@ -287,24 +289,9 @@ public async Task DoFinalizeAsync(IEnumerable outputTokens = null) input ); - //lock (Context.Streams) - //{ - // if ( - // node.OutputNode != null && - // Context.OutputTokens.TryGetValue(nodeScope.ThreadId, out var nodesOutputTokens) && - // nodesOutputTokens.TryGetValue(node.OutputNode.Identifier, out var tokens) - // ) - // { - // outputTokens.AddRange(Context.GetOutputTokens(node.OutputNode.Identifier, nodeScope.ThreadId)); - // } - - // Context.Streams.Remove(nodeScope.ThreadId); - // Context.OutputTokens.Remove(nodeScope.ThreadId); - //} - var output = node.OutputNode != null ? Context.GetOutputTokens(node.OutputNode.Identifier, nodeScope.ThreadId) - : new List(); + : new List(); if (node.ExceptionHandlers.Any()) { @@ -324,17 +311,18 @@ public async Task DoFinalizeAsync(IEnumerable outputTokens = null) return result; } - public async Task> DoExecuteParallelNodeAsync(Node node, NodeScope nodeScope, IEnumerable input = null) - where TToken : Token, new() + public async Task> DoExecuteParallelNodeAsync(Node node, NodeScope nodeScope, IEnumerable input = null) { - var restOfInput = input.Where(t => !(t is TToken)).ToArray(); + var typedInput = input.OfType>().ToArray(); - var parallelInput = input.OfType().Partition(node.ChunkSize).ToArray(); + var restOfInput = input.Except(typedInput).ToArray(); - var outputTokens = new List(); + var inputPartitions = typedInput.Partition(node.ChunkSize).ToArray(); - await Task.WhenAll(parallelInput - .Select(tokensPartition => + var outputTokens = new List(); + + await Task.WhenAll(inputPartitions + .Select(inputPartition => Task.Run(async () => { var threadId = Guid.NewGuid(); @@ -342,8 +330,8 @@ await Task.WhenAll(parallelInput await DoExecuteStructureAsync( node, nodeScope.CreateChildScope(node, threadId), - restOfInput.Concat(tokensPartition).ToArray(), - tokensPartition + restOfInput.Concat(inputPartition).ToArray(), + inputPartition ); lock (Context.Streams) @@ -366,7 +354,7 @@ await DoExecuteStructureAsync( return node.OutputNode != null ? outputTokens - : new List(); + : new List(); } public async Task DoInitializeNodeAsync(Node node, ActionContext context) @@ -387,24 +375,25 @@ public async Task DoFinalizeNodeAsync(Node node, ActionContext context) await Inspector.AfterNodeFinalizationAsync(context); } - public async Task> DoExecuteIterativeNodeAsync(ActionContext context) - where TToken : Token, new() + public async Task> DoExecuteIterativeNodeAsync(ActionContext context) { - var restOfInput = context.InputTokens.Where(t => !(t is TToken)).ToArray(); + var typedInput = context.InputTokens.OfType>().ToArray(); + + var restOfInput = context.InputTokens.Except(typedInput).ToArray(); - var iterativeInput = context.InputTokens.OfType().ToArray(); + var inputPartitions = typedInput.Partition(context.Node.ChunkSize).ToArray(); var threadId = Guid.NewGuid(); - var outputTokens = new List(); + var outputTokens = new List(); - foreach (var tokensPartition in iterativeInput.Partition(context.Node.ChunkSize)) + foreach (var inputPartition in inputPartitions) { await DoExecuteStructureAsync( context.Node, context.NodeScope.CreateChildScope(context.Node, threadId), - restOfInput.Concat(tokensPartition), - tokensPartition + restOfInput.Concat(inputPartition), + inputPartition ); if ( @@ -425,10 +414,10 @@ await DoExecuteStructureAsync( return context.Node.OutputNode != null ? outputTokens - : new List(); + : new List(); } - private async Task DoExecuteStructureAsync(Node node, NodeScope nodeScope, IEnumerable input = null, IEnumerable selectionTokens = null) + private async Task DoExecuteStructureAsync(Node node, NodeScope nodeScope, IEnumerable input = null, IEnumerable selectionTokens = null) { var startingNode = Context.NodesToExecute.Any() ? node.Nodes.Values.FirstOrDefault(n => Context.NodesToExecute.Contains(n)) @@ -490,13 +479,16 @@ public async Task DoInitializeActivityAsync(InitializationRequest @event) return result; } - public async Task> HandleExceptionAsync(Node node, Exception exception, BaseContext context) + public async Task> HandleExceptionAsync(Node node, Exception exception, BaseContext context) { Node handler = null; var currentNode = node; while (currentNode != null) { - handler = currentNode.ExceptionHandlers.FirstOrDefault(n => exception.GetType().IsAssignableFrom(n.ExceptionType)); + var handlers = currentNode.ExceptionHandlers.Where(n => n.ExceptionType.IsAssignableFrom(exception.GetType())); + handler = handlers.Any() + ? handlers.FirstOrDefault(n => n.ExceptionType == exception.GetType()) ?? handlers.First() + : null; if (handler != null) { @@ -526,22 +518,26 @@ public async Task> HandleExceptionAsync(Node node, Exception context.Context, currentScope, handler, - new Token[] { new ExceptionToken() { Exception = exception } } + new TokenHolder[] + { + exception.ToExceptionHolder(exception.GetType()), + new NodeReference() { Node = node }.ToTokenHolder(), + } ); await handler.Action.WhenAll(exceptionContext); DoHandleOutput(exceptionContext); - ReportExceptionHandled(node, exceptionName, exceptionContext.OutputTokens.Where(t => t.Name != TokenInfo.Name).ToArray()); + ReportExceptionHandled(node, exceptionName, exceptionContext.OutputTokens.Where(t => t is TokenHolder).ToArray()); return exceptionContext.OutputTokens; } - return new Token[0]; + return new TokenHolder[0]; } - public async Task DoHandleNodeAsync(Node node, NodeScope nodeScope, IEnumerable input = null, IEnumerable selectionTokens = null) + public async Task DoHandleNodeAsync(Node node, NodeScope nodeScope, IEnumerable input = null, IEnumerable selectionTokens = null) { if (CancellableTypes.Contains(node.Type) && nodeScope.CancellationToken.IsCancellationRequested) { @@ -558,7 +554,7 @@ public async Task DoHandleNodeAsync(Node node, NodeScope nodeScope, IEnumerable< } } - if ( + var activated = ( // initial node case node.Type == NodeType.Initial ) || @@ -576,8 +572,17 @@ public async Task DoHandleNodeAsync(Node node, NodeScope nodeScope, IEnumerable< ) || ( Context.NodesToExecute.Contains(node) - ) - ) + ); + + var inputTokens = input ?? streams.SelectMany(stream => stream.Tokens).Distinct().ToArray(); + + nodeScope = nodeScope.CreateChildScope(node); + + var actionContext = new ActionContext(Context, nodeScope, node, inputTokens, selectionTokens); + + await Inspector.BeforeNodeActivateAsync(actionContext, activated); + + if (activated) { if ( node.Type == NodeType.AcceptEventAction && @@ -597,13 +602,13 @@ public async Task DoHandleNodeAsync(Node node, NodeScope nodeScope, IEnumerable< return; } - var inputTokens = input ?? streams.GetTokens(); + //var inputTokens = input ?? streams.SelectMany(stream => stream.Tokens).Distinct().ToArray(); ReportNodeExecuting(node, inputTokens); - nodeScope = nodeScope.CreateChildScope(node); + //nodeScope = nodeScope.CreateChildScope(node); - var actionContext = new ActionContext(Context, nodeScope, node, inputTokens, selectionTokens); + //var actionContext = new ActionContext(Context, nodeScope, node, inputTokens, selectionTokens); await node.Action.WhenAll(actionContext); @@ -637,26 +642,24 @@ public async Task DoHandleNodeAsync(Node node, NodeScope nodeScope, IEnumerable< } else { - List outputTokens; - lock (actionContext.OutputTokens) - { - outputTokens = actionContext.OutputTokens.ToList(); - } - - ReportNodeExecuted(node, outputTokens.Where(t => t.Name != TokenInfo.Name).ToArray()); - if ( StructuralTypes.Contains(node.Type) && - ( - Context.IsNodeCompleted(node, nodeScope) || - outputTokens.Any() - ) + Context.IsNodeCompleted(node, nodeScope) && + !actionContext.OutputTokens.Any() ) { - outputTokens.Add(new ControlToken()); + actionContext.OutputTokens.Add(new Control().ToTokenHolder()); + } + + List outputTokens; + lock (actionContext.OutputTokens) + { + outputTokens = actionContext.OutputTokens.ToList(); } - if (outputTokens.Any(t => t is ControlToken)) + ReportNodeExecuted(node, outputTokens.Where(t => t is TokenHolder).ToArray()); + + if (outputTokens.Any(t => t is TokenHolder)) { var tokenNames = outputTokens.Select(token => token.Name).Distinct().ToArray(); var edges = node.Edges @@ -690,13 +693,15 @@ public async Task DoHandleNodeAsync(Node node, NodeScope nodeScope, IEnumerable< { ReportNodeAttemptedExecution(node, streams); } + + await Inspector.AfterNodeActivateAsync(null); } - private static void ReportNodeExecuting(Node node, IEnumerable inputTokens) + private static void ReportNodeExecuting(Node node, IEnumerable inputTokens) { if (Debugger.IsAttached) { - lock (node.Graph) + lock (lockHandle) { Trace.WriteLine($"⦗→s⦘ Activity '{node.Graph.Name}': executing '{node.Name}'{(!inputTokens.Any() ? ", no input" : "")}"); ReportTokens(inputTokens); @@ -704,11 +709,11 @@ private static void ReportNodeExecuting(Node node, IEnumerable inputToken } } - private static void ReportNodeExecuted(Node node, IEnumerable outputTokens) + private static void ReportNodeExecuted(Node node, IEnumerable outputTokens) { if (Debugger.IsAttached) { - lock (node.Graph) + lock (lockHandle) { Trace.WriteLine($"⦗→s⦘ Activity '{node.Graph.Name}': executed '{node.Name}'{(!outputTokens.Any() ? ", no output" : "")}"); ReportTokens(outputTokens, false); @@ -716,11 +721,11 @@ private static void ReportNodeExecuted(Node node, IEnumerable outputToken } } - private static void ReportExceptionHandled(Node node, string exceptionName, IEnumerable outputTokens) + private static void ReportExceptionHandled(Node node, string exceptionName, IEnumerable outputTokens) { if (Debugger.IsAttached) { - lock (node.Graph) + lock (lockHandle) { Trace.WriteLine($"⦗→s⦘ Activity '{node.Graph.Name}': '{exceptionName}' handled{(!outputTokens.Any() ? ", no output" : "")}"); ReportTokens(outputTokens, false); @@ -732,10 +737,10 @@ private static void ReportNodeAttemptedExecution(Node node, IEnumerable { if (Debugger.IsAttached) { - lock (node.Graph) + lock (lockHandle) { Trace.WriteLine($"⦗→s⦘ Activity '{node.Graph.Name}': omitting '{node.Name}'"); - ReportTokens(streams.GetTokens()); + ReportTokens(streams.SelectMany(stream => stream.Tokens).Distinct().ToArray()); var activatedFlows = streams.Select(s => s.EdgeIdentifier).ToArray(); var missingFlows = node.IncomingEdges.Where(e => !activatedFlows.Contains(e.Identifier)); ReportMissingFlows(missingFlows); @@ -743,7 +748,7 @@ private static void ReportNodeAttemptedExecution(Node node, IEnumerable } } - private static void ReportTokens(IEnumerable inputTokens, bool input = true) + private static void ReportTokens(IEnumerable inputTokens, bool input = true) { var inputDigest = inputTokens .GroupBy(t => t.Name) @@ -772,7 +777,7 @@ private static void ReportMissingFlows(IEnumerable flows) foreach (var flow in flows) { var tokenName = flow.TargetTokenType.GetTokenName(); - if (tokenName == TokenInfo.Name) + if (tokenName == typeof(Control).GetTokenName()) { Trace.WriteLine($" - control flow from '{flow.SourceName}' "); } @@ -791,15 +796,10 @@ private async Task DoHandleEdgeAsync(Edge edge, ActionContext context) { var edgeTokenName = edge.TokenType.GetTokenName(); - IEnumerable originalTokens = context.OutputTokens.Where(t => t.Name == edgeTokenName).ToArray(); - - if (!originalTokens.Any()) - { - return false; - } + IEnumerable originalTokens = context.OutputTokens.Where(t => t.Name == edgeTokenName).ToArray(); - var consumedTokens = new List(); - var processedTokens = new List(); + var consumedTokens = new List(); + var processedTokens = new List(); foreach (var token in originalTokens) { @@ -826,9 +826,9 @@ private async Task DoHandleEdgeAsync(Edge edge, ActionContext context) { var stream = Context.GetStream(edge.Identifier, context.NodeScope.ThreadId); - if (edgeTokenName != TokenInfo.Name) + if (edgeTokenName != typeof(Control).GetTokenName()) { - processedTokens.Add(new ControlToken()); + processedTokens.Add(new Control().ToTokenHolder()); } if (!edge.Source.Options.HasFlag(NodeOptions.ImplicitFork) && consumedTokens.Any()) diff --git a/Core/Stateflows/Activities/Engine/Inspector.cs b/Core/Stateflows/Activities/Engine/Inspector.cs index 5bd8fafa..30ca3c7c 100644 --- a/Core/Stateflows/Activities/Engine/Inspector.cs +++ b/Core/Stateflows/Activities/Engine/Inspector.cs @@ -113,58 +113,58 @@ public async Task AfterProcessEventAsync(Context.Classes.EventContext p.BeforeActivityInitializationAsync(context), nameof(BeforeActivityInitializationAsync), Logger); - await Inspectors.RunSafe(i => i.BeforeActivityInitializationAsync(context), nameof(BeforeActivityInitializationAsync), Logger); - await Observers.RunSafe(o => o.BeforeActivityInitializationAsync(context), nameof(BeforeActivityInitializationAsync), Logger); + await Plugins.RunSafe(p => p.BeforeActivityInitializeAsync(context), nameof(BeforeActivityInitializationAsync), Logger); + await Inspectors.RunSafe(i => i.BeforeActivityInitializeAsync(context), nameof(BeforeActivityInitializationAsync), Logger); + await Observers.RunSafe(o => o.BeforeActivityInitializeAsync(context), nameof(BeforeActivityInitializationAsync), Logger); } public async Task AfterActivityInitializationAsync(ActivityInitializationContext context) { - await Observers.RunSafe(o => o.AfterActivityInitializationAsync(context), nameof(AfterActivityInitializationAsync), Logger); - await Inspectors.RunSafe(i => i.AfterActivityInitializationAsync(context), nameof(AfterActivityInitializationAsync), Logger); - await Plugins.RunSafe(p => p.AfterActivityInitializationAsync(context), nameof(AfterActivityInitializationAsync), Logger); + await Observers.RunSafe(o => o.AfterActivityInitializeAsync(context), nameof(AfterActivityInitializationAsync), Logger); + await Inspectors.RunSafe(i => i.AfterActivityInitializeAsync(context), nameof(AfterActivityInitializationAsync), Logger); + await Plugins.RunSafe(p => p.AfterActivityInitializeAsync(context), nameof(AfterActivityInitializationAsync), Logger); } public async Task BeforeActivityFinalizationAsync(ActivityActionContext context) { - await Plugins.RunSafe(p => p.BeforeActivityFinalizationAsync(context), nameof(BeforeActivityFinalizationAsync), Logger); - await Inspectors.RunSafe(i => i.BeforeActivityFinalizationAsync(context), nameof(BeforeActivityFinalizationAsync), Logger); - await Observers.RunSafe(o => o.BeforeActivityFinalizationAsync(context), nameof(BeforeActivityFinalizationAsync), Logger); + await Plugins.RunSafe(p => p.BeforeActivityFinalizeAsync(context), nameof(BeforeActivityFinalizationAsync), Logger); + await Inspectors.RunSafe(i => i.BeforeActivityFinalizeAsync(context), nameof(BeforeActivityFinalizationAsync), Logger); + await Observers.RunSafe(o => o.BeforeActivityFinalizeAsync(context), nameof(BeforeActivityFinalizationAsync), Logger); } public async Task AfterActivityFinalizationAsync(ActivityActionContext context) { - await Observers.RunSafe(o => o.AfterActivityFinalizationAsync(context), nameof(AfterActivityFinalizationAsync), Logger); - await Inspectors.RunSafe(i => i.AfterActivityFinalizationAsync(context), nameof(AfterActivityFinalizationAsync), Logger); - await Plugins.RunSafe(p => p.AfterActivityFinalizationAsync(context), nameof(AfterActivityFinalizationAsync), Logger); + await Observers.RunSafe(o => o.AfterActivityFinalizeAsync(context), nameof(AfterActivityFinalizationAsync), Logger); + await Inspectors.RunSafe(i => i.AfterActivityFinalizeAsync(context), nameof(AfterActivityFinalizationAsync), Logger); + await Plugins.RunSafe(p => p.AfterActivityFinalizeAsync(context), nameof(AfterActivityFinalizationAsync), Logger); } public async Task BeforeNodeInitializationAsync(ActionContext context) { - await Plugins.RunSafe(p => p.BeforeNodeInitializationAsync(context), nameof(BeforeNodeInitializationAsync), Logger); - await Inspectors.RunSafe(i => i.BeforeNodeInitializationAsync(context), nameof(BeforeNodeInitializationAsync), Logger); - await Observers.RunSafe(o => o.BeforeNodeInitializationAsync(context), nameof(BeforeNodeInitializationAsync), Logger); + await Plugins.RunSafe(p => p.BeforeNodeInitializeAsync(context), nameof(BeforeNodeInitializationAsync), Logger); + await Inspectors.RunSafe(i => i.BeforeNodeInitializeAsync(context), nameof(BeforeNodeInitializationAsync), Logger); + await Observers.RunSafe(o => o.BeforeNodeInitializeAsync(context), nameof(BeforeNodeInitializationAsync), Logger); } public async Task AfterNodeInitializationAsync(ActionContext context) { - await Observers.RunSafe(o => o.AfterNodeInitializationAsync(context), nameof(AfterNodeInitializationAsync), Logger); - await Inspectors.RunSafe(i => i.AfterNodeInitializationAsync(context), nameof(AfterNodeInitializationAsync), Logger); - await Plugins.RunSafe(p => p.AfterNodeInitializationAsync(context), nameof(AfterNodeInitializationAsync), Logger); + await Observers.RunSafe(o => o.AfterNodeInitializeAsync(context), nameof(AfterNodeInitializationAsync), Logger); + await Inspectors.RunSafe(i => i.AfterNodeInitializeAsync(context), nameof(AfterNodeInitializationAsync), Logger); + await Plugins.RunSafe(p => p.AfterNodeInitializeAsync(context), nameof(AfterNodeInitializationAsync), Logger); } public async Task BeforeNodeFinalizationAsync(ActionContext context) { - await Plugins.RunSafe(p => p.BeforeNodeFinalizationAsync(context), nameof(BeforeNodeFinalizationAsync), Logger); - await Inspectors.RunSafe(i => i.BeforeNodeFinalizationAsync(context), nameof(BeforeNodeFinalizationAsync), Logger); - await Observers.RunSafe(o => o.BeforeNodeFinalizationAsync(context), nameof(BeforeNodeFinalizationAsync), Logger); + await Plugins.RunSafe(p => p.BeforeNodeFinalizeAsync(context), nameof(BeforeNodeFinalizationAsync), Logger); + await Inspectors.RunSafe(i => i.BeforeNodeFinalizeAsync(context), nameof(BeforeNodeFinalizationAsync), Logger); + await Observers.RunSafe(o => o.BeforeNodeFinalizeAsync(context), nameof(BeforeNodeFinalizationAsync), Logger); } public async Task AfterNodeFinalizationAsync(ActionContext context) { - await Observers.RunSafe(o => o.AfterNodeFinalizationAsync(context), nameof(AfterNodeFinalizationAsync), Logger); - await Inspectors.RunSafe(i => i.AfterNodeFinalizationAsync(context), nameof(AfterNodeFinalizationAsync), Logger); - await Plugins.RunSafe(p => p.AfterNodeFinalizationAsync(context), nameof(AfterNodeFinalizationAsync), Logger); + await Observers.RunSafe(o => o.AfterNodeFinalizeAsync(context), nameof(AfterNodeFinalizationAsync), Logger); + await Inspectors.RunSafe(i => i.AfterNodeFinalizeAsync(context), nameof(AfterNodeFinalizationAsync), Logger); + await Plugins.RunSafe(p => p.AfterNodeFinalizeAsync(context), nameof(AfterNodeFinalizationAsync), Logger); } public async Task BeforeNodeExecuteAsync(ActionContext context) @@ -181,6 +181,20 @@ public async Task AfterNodeExecuteAsync(ActionContext context) await Plugins.RunSafe(p => p.AfterNodeExecuteAsync(context), nameof(AfterNodeExecuteAsync), Logger); } + public async Task BeforeNodeActivateAsync(ActionContext context, bool activated) + { + await Plugins.RunSafe(p => p.BeforeNodeActivateAsync(context, activated), nameof(BeforeNodeActivateAsync), Logger); + await Inspectors.RunSafe(i => i.BeforeNodeActivateAsync(context, activated), nameof(BeforeNodeActivateAsync), Logger); + await Observers.RunSafe(o => o.BeforeNodeActivateAsync(context, activated), nameof(BeforeNodeActivateAsync), Logger); + } + + public async Task AfterNodeActivateAsync(ActionContext context) + { + await Observers.RunSafe(o => o.AfterNodeActivateAsync(context), nameof(AfterNodeActivateAsync), Logger); + await Inspectors.RunSafe(i => i.AfterNodeActivateAsync(context), nameof(AfterNodeActivateAsync), Logger); + await Plugins.RunSafe(p => p.AfterNodeActivateAsync(context), nameof(AfterNodeActivateAsync), Logger); + } + public async Task OnActivityInitializationExceptionAsync(BaseContext context, InitializationRequest initializationRequest, Exception exception) { var exceptionContext = new ActivityInitializationContext(context, initializationRequest); diff --git a/Core/Stateflows/Activities/Engine/NodeScope.cs b/Core/Stateflows/Activities/Engine/NodeScope.cs index b642c670..afe15e8e 100644 --- a/Core/Stateflows/Activities/Engine/NodeScope.cs +++ b/Core/Stateflows/Activities/Engine/NodeScope.cs @@ -2,6 +2,7 @@ using System.Threading; using Microsoft.Extensions.DependencyInjection; using Stateflows.Common; +using Stateflows.Common.Classes; using Stateflows.Activities.Models; using Stateflows.Activities.Context.Interfaces; @@ -74,74 +75,87 @@ public NodeScope CreateChildScope(Node node = null, Guid? threadId = null) public TAction GetAction(IActionContext context) where TAction : ActionNode { - var action = ServiceProvider.GetService(); - action.Context = context; + ContextValuesHolder.GlobalValues.Value = context.Activity.Values; + ContextValuesHolder.StateValues.Value = null; + ContextValuesHolder.SourceStateValues.Value = null; + ContextValuesHolder.TargetStateValues.Value = null; - return action; + return ServiceProvider.GetService(); } public TAcceptEventAction GetAcceptEventAction(IAcceptEventActionContext context) where TEvent : Event, new() where TAcceptEventAction : AcceptEventActionNode { - var acceptEventAction = ServiceProvider.GetService(); - acceptEventAction.Context = context; + ContextValuesHolder.GlobalValues.Value = context.Activity.Values; + ContextValuesHolder.StateValues.Value = null; + ContextValuesHolder.SourceStateValues.Value = null; + ContextValuesHolder.TargetStateValues.Value = null; - return acceptEventAction; + return ServiceProvider.GetService(); } public TSendEventAction GetSendEventAction(IActionContext context) where TEvent : Event, new() where TSendEventAction : SendEventActionNode { - var acceptEventAction = ServiceProvider.GetService(); - acceptEventAction.Context = context; + ContextValuesHolder.GlobalValues.Value = context.Activity.Values; + ContextValuesHolder.StateValues.Value = null; + ContextValuesHolder.SourceStateValues.Value = null; + ContextValuesHolder.TargetStateValues.Value = null; - return acceptEventAction; + return ServiceProvider.GetService(); } public TStructuredActivity GetStructuredActivity(IActionContext context) where TStructuredActivity : StructuredActivityNode { - var structuredActivity = ServiceProvider.GetService(); - structuredActivity.Context = context; + ContextValuesHolder.GlobalValues.Value = context.Activity.Values; + ContextValuesHolder.StateValues.Value = null; + ContextValuesHolder.SourceStateValues.Value = null; + ContextValuesHolder.TargetStateValues.Value = null; - return structuredActivity; + return ServiceProvider.GetService(); } public TExceptionHandler GetExceptionHandler(IExceptionHandlerContext context) where TException : Exception where TExceptionHandler : ExceptionHandlerNode { - var exceptionHandler = ServiceProvider.GetService(); - exceptionHandler.Context = context; + ContextValuesHolder.GlobalValues.Value = context.Activity.Values; + ContextValuesHolder.StateValues.Value = null; + ContextValuesHolder.SourceStateValues.Value = null; + ContextValuesHolder.TargetStateValues.Value = null; - return exceptionHandler; + return ServiceProvider.GetService(); } - public TFlow GetFlow(IFlowContext context) + public TFlow GetFlow(IActivityFlowContext context) where TFlow : BaseControlFlow { - var flow = ServiceProvider.GetService(); - flow.Context = context; + ContextValuesHolder.GlobalValues.Value = context.Activity.Values; + ContextValuesHolder.StateValues.Value = null; + ContextValuesHolder.SourceStateValues.Value = null; + ContextValuesHolder.TargetStateValues.Value = null; - return flow; + return ServiceProvider.GetService(); } - public TControlFlow GetControlFlow(IFlowContext context) + public TControlFlow GetControlFlow(IActivityFlowContext context) where TControlFlow : ControlFlow => GetFlow(context); - public TFlow GetObjectFlow(IFlowContext context) + public TFlow GetObjectFlow(IActivityFlowContext context) where TFlow : Flow - where TToken : Token, new() => GetFlow(context); - public TFlow GetObjectTransformationFlow(IFlowContext context) - where TFlow : TransformationFlow - where TToken : Token, new() - where TTransformedToken : Token, new() - => GetFlow(context); + public TTransformationFlow GetObjectTransformationFlow(IActivityFlowContext context) + where TTransformationFlow : TransformationFlow + => GetFlow(context); + + public TElseTransformationFlow GetElseObjectTransformationFlow(IActivityFlowContext context) + where TElseTransformationFlow : ElseTransformationFlow + => GetFlow(context); public void Dispose() { diff --git a/Core/Stateflows/Activities/Engine/Plugins/AcceptEvents.cs b/Core/Stateflows/Activities/Engine/Plugins/AcceptEvents.cs index edac37f4..ebbe8b7e 100644 --- a/Core/Stateflows/Activities/Engine/Plugins/AcceptEvents.cs +++ b/Core/Stateflows/Activities/Engine/Plugins/AcceptEvents.cs @@ -6,9 +6,6 @@ using Stateflows.Activities.Models; using Stateflows.Activities.Context.Classes; using Stateflows.Activities.Context.Interfaces; -using System.Xml.Linq; -using Microsoft.Extensions.Logging; -using System.Diagnostics; namespace Stateflows.Activities.Engine { @@ -102,36 +99,24 @@ public void UnregisterAcceptEventNode(Node node) } } - Task IActivityObserver.AfterActivityInitializationAsync(IActivityInitializationContext context) + Task IActivityObserver.AfterActivityInitializeAsync(IActivityInitializationContext context) => Task.CompletedTask; - Task IActivityObserver.AfterActivityFinalizationAsync(IActivityFinalizationContext context) + Task IActivityObserver.AfterActivityFinalizeAsync(IActivityFinalizationContext context) { UnregisterAcceptEventNodes((context as IRootContext).Context.Executor.Graph.DanglingTimeEventActionNodes); return Task.CompletedTask; } - Task IActivityObserver.AfterFlowGuardAsync(IGuardContext context, bool guardResult) - => Task.CompletedTask; - - Task IActivityObserver.AfterFlowTransformationAsync(ITransformationContext context) - => Task.CompletedTask; - - Task IActivityInterceptor.AfterHydrateAsync(IActivityActionContext context) - => Task.CompletedTask; - - Task IActivityObserver.AfterNodeExecuteAsync(IActivityNodeContext context) - => Task.CompletedTask; - - Task IActivityObserver.AfterNodeFinalizationAsync(IActivityNodeContext context) + Task IActivityObserver.AfterNodeFinalizeAsync(IActivityNodeContext context) { UnregisterAcceptEventNodes((context as ActionContext).Node.DanglingTimeEventActionNodes); return Task.CompletedTask; } - Task IActivityObserver.AfterNodeInitializationAsync(IActivityNodeContext context) + Task IActivityObserver.AfterNodeInitializeAsync(IActivityNodeContext context) => Task.CompletedTask; Task IActivityInterceptor.AfterProcessEventAsync(IEventContext context) @@ -153,7 +138,7 @@ Task IActivityInterceptor.AfterProcessEventAsync(IEventContext context) return Task.CompletedTask; } - Task IActivityObserver.BeforeActivityInitializationAsync(IActivityInitializationContext context) + Task IActivityObserver.BeforeActivityInitializeAsync(IActivityInitializationContext context) { RegisterAcceptEventNodes( (context as IRootContext).Context.Executor.Graph.AcceptEventActionNodes.Select(node => (node, Guid.NewGuid())) @@ -162,22 +147,7 @@ Task IActivityObserver.BeforeActivityInitializationAsync(IActivityInitialization return Task.CompletedTask; } - Task IActivityObserver.BeforeActivityFinalizationAsync(IActivityFinalizationContext context) - => Task.CompletedTask; - - Task IActivityInterceptor.BeforeDehydrateAsync(IActivityActionContext context) - => Task.CompletedTask; - - Task IActivityObserver.BeforeFlowGuardAsync(IGuardContext context) - => Task.CompletedTask; - - Task IActivityObserver.BeforeFlowTransformationAsync(ITransformationContext context) - => Task.CompletedTask; - - Task IActivityObserver.BeforeNodeExecuteAsync(IActivityNodeContext context) - => Task.CompletedTask; - - Task IActivityObserver.BeforeNodeInitializationAsync(IActivityNodeContext context) + Task IActivityObserver.BeforeNodeInitializeAsync(IActivityNodeContext context) { RegisterAcceptEventNodes( (context as ActionContext).Node.DanglingTimeEventActionNodes.Select(node => (node, Guid.NewGuid())) @@ -186,7 +156,7 @@ Task IActivityObserver.BeforeNodeInitializationAsync(IActivityNodeContext contex return Task.CompletedTask; } - Task IActivityObserver.BeforeNodeFinalizationAsync(IActivityNodeContext context) + Task IActivityObserver.BeforeNodeFinalizeAsync(IActivityNodeContext context) => Task.CompletedTask; Task IActivityInterceptor.BeforeProcessEventAsync(IEventContext context) @@ -202,26 +172,5 @@ Task IActivityInterceptor.BeforeProcessEventAsync(IEventContext con return Task.FromResult(result); } - - public Task OnActivityInitializationExceptionAsync(IActivityInitializationContext context, Exception exception) - => Task.CompletedTask; - - public Task OnActivityFinalizationExceptionAsync(IActivityFinalizationContext context, Exception exception) - => Task.CompletedTask; - - public Task OnNodeInitializationExceptionAsync(IActivityNodeContext context, Exception exception) - => Task.CompletedTask; - - public Task OnNodeFinalizationExceptionAsync(IActivityNodeContext context, Exception exception) - => Task.CompletedTask; - - public Task OnNodeExecutionExceptionAsync(IActivityNodeContext context, Exception exception) - => Task.CompletedTask; - - public Task OnFlowGuardExceptionAsync(IGuardContext context, Exception exception) - => Task.CompletedTask; - - public Task OnFlowTransformationExceptionAsync(ITransformationContext context, Exception exception) - => Task.CompletedTask; } } diff --git a/Core/Stateflows/Activities/Engine/Plugins/Tracer.cs b/Core/Stateflows/Activities/Engine/Plugins/Tracer.cs index b25a19c1..40ea65d4 100644 --- a/Core/Stateflows/Activities/Engine/Plugins/Tracer.cs +++ b/Core/Stateflows/Activities/Engine/Plugins/Tracer.cs @@ -69,28 +69,28 @@ private Task SetExceptionAsync(Exception exception) return Task.CompletedTask; } - public Task BeforeActivityInitializationAsync(IActivityInitializationContext context) + public Task BeforeActivityInitializeAsync(IActivityInitializationContext context) => StartMeasureAsync(); - public Task AfterActivityInitializationAsync(IActivityInitializationContext context) + public Task AfterActivityInitializeAsync(IActivityInitializationContext context) => StopMeasureAsync("ActivityInitialization", context.Activity.Id.Name); - public Task BeforeActivityFinalizationAsync(IActivityFinalizationContext context) + public Task BeforeActivityFinalizeAsync(IActivityFinalizationContext context) => StartMeasureAsync(); - public Task AfterActivityFinalizationAsync(IActivityFinalizationContext context) + public Task AfterActivityFinalizeAsync(IActivityFinalizationContext context) => StopMeasureAsync("ActivityFinalization", context.Activity.Id.Name); - public Task BeforeNodeInitializationAsync(IActivityNodeContext context) + public Task BeforeNodeInitializeAsync(IActivityNodeContext context) => StartMeasureAsync(); - public Task AfterNodeInitializationAsync(IActivityNodeContext context) + public Task AfterNodeInitializeAsync(IActivityNodeContext context) => StopMeasureAsync("NodeInitialization", context.CurrentNode.NodeName); - public Task BeforeNodeFinalizationAsync(IActivityNodeContext context) + public Task BeforeNodeFinalizeAsync(IActivityNodeContext context) => StartMeasureAsync(); - public Task AfterNodeFinalizationAsync(IActivityNodeContext context) + public Task AfterNodeFinalizeAsync(IActivityNodeContext context) => StopMeasureAsync("NodeFinalization", context.CurrentNode.NodeName); public Task BeforeNodeExecuteAsync(IActivityNodeContext context) @@ -106,8 +106,8 @@ public Task AfterNodeExecuteAsync(IActivityNodeContext context) .AddStep( "Execute", context.CurrentNode.NodeName, - Stopwatch.Elapsed, - (context as IActionContext)?.Input ?? Array.Empty() + Stopwatch.Elapsed + //(context as IActionContext)?.Input ?? Array.Empty() ) .Exceptions .Add(Exception); @@ -116,17 +116,17 @@ public Task AfterNodeExecuteAsync(IActivityNodeContext context) return Task.CompletedTask; } - public Task BeforeFlowGuardAsync(IGuardContext context) + public Task BeforeFlowGuardAsync(IGuardContext context) => StartMeasureAsync(); - public Task AfterFlowGuardAsync(IGuardContext context, bool guardResult) - => StopMeasureAsync("Guard", $"{context.SourceNode.NodeName}-{context.Token.Name}->{context.TargetNode.NodeName}"); + public Task AfterFlowGuardAsync(IGuardContext context, bool guardResult) + => StopMeasureAsync("Guard", $"{context.SourceNode.NodeName}-{context.Token.GetType().GetTokenName()}->{context.TargetNode.NodeName}"); - public Task BeforeFlowTransformationAsync(ITransformationContext context) + public Task BeforeFlowTransformAsync(ITransformationContext context) => StartMeasureAsync(); - public Task AfterFlowTransformationAsync(ITransformationContext context) - => StopMeasureAsync("Transformation", $"{context.SourceNode.NodeName}-{context.Token.Name}->{context.TargetNode.NodeName}"); + public Task AfterFlowTransformAsync(ITransformationContext context) + => StopMeasureAsync("Transformation", $"{context.SourceNode.NodeName}-{context.Token.GetType().GetTokenName()}->{context.TargetNode.NodeName}"); public Task OnActivityInitializationExceptionAsync(IActivityInitializationContext context, Exception exception) => SetExceptionAsync(exception); @@ -143,18 +143,12 @@ public Task OnNodeFinalizationExceptionAsync(IActivityNodeContext context, Excep public Task OnNodeExecutionExceptionAsync(IActivityNodeContext context, Exception exception) => SetExceptionAsync(exception); - public Task OnFlowGuardExceptionAsync(IGuardContext context, Exception exception) + public Task OnFlowGuardExceptionAsync(IGuardContext context, Exception exception) => SetExceptionAsync(exception); - public Task OnFlowTransformationExceptionAsync(ITransformationContext context, Exception exception) + public Task OnFlowTransformationExceptionAsync(ITransformationContext context, Exception exception) => SetExceptionAsync(exception); - public Task AfterHydrateAsync(IActivityActionContext context) - => Task.CompletedTask; - - public Task BeforeDehydrateAsync(IActivityActionContext context) - => Task.CompletedTask; - public Task BeforeProcessEventAsync(IEventContext context) { var eventType = context.Event.GetType(); diff --git a/Core/Stateflows/Activities/Engine/Provider.cs b/Core/Stateflows/Activities/Engine/Provider.cs index e2e894f0..7907212f 100644 --- a/Core/Stateflows/Activities/Engine/Provider.cs +++ b/Core/Stateflows/Activities/Engine/Provider.cs @@ -26,9 +26,7 @@ public Provider(ActivitiesRegister register, StateflowsEngine engine, IServicePr ServiceProvider = serviceProvider; } -#pragma warning disable CS0067 // The event 'Provider.BehaviorClassesChanged' is never used public event ActionAsync BehaviorClassesChanged; -#pragma warning restore CS0067 // The event 'Provider.BehaviorClassesChanged' is never used public bool TryProvideBehavior(BehaviorId id, out IBehavior behavior) { diff --git a/Core/Stateflows/Activities/Extensions/BuilderExtensions.cs b/Core/Stateflows/Activities/Extensions/BuilderExtensions.cs index ff5ca7a7..07dcbf18 100644 --- a/Core/Stateflows/Activities/Extensions/BuilderExtensions.cs +++ b/Core/Stateflows/Activities/Extensions/BuilderExtensions.cs @@ -4,11 +4,11 @@ using System.Runtime.Serialization; using Stateflows.Common; using Stateflows.Common.Extensions; +using Stateflows.Activities.Events; using Stateflows.Activities.Context.Classes; using Stateflows.Activities.Context.Interfaces; using Stateflows.Activities.Registration.Builders; using Stateflows.Activities.Registration.Interfaces; -using Stateflows.Activities.Events; namespace Stateflows.Activities.Extensions { @@ -41,7 +41,7 @@ public static void AddActivityEvents(this IActivityBuilder builder, Type activit { var methodInfo = interfaceType.GetMethods().First(m => m.Name == "OnInitializeAsync"); var requestType = interfaceType.GenericTypeArguments[0]; - var requestName = Stateflows.Common.EventInfo.GetName(requestType); + var requestName = requestType.GetEventName(); (builder as ActivityBuilder).AddInitializer(requestType, requestName, c => { var activity = c.Context.Executor.GetActivity(activityType, c.Context); @@ -56,52 +56,150 @@ public static void AddStructuredActivityEvents(this Structu { if (typeof(StructuredActivityNode).GetMethod(nameof(StructuredActivityNode.OnInitializeAsync)).IsOverridenIn()) { - builder.AddOnInitialize(c => (c as BaseContext).NodeScope.GetStructuredActivity(c as IActionContext)?.OnInitializeAsync()); + builder.AddOnInitialize(async c => + { + var node = (c as BaseContext).NodeScope.GetStructuredActivity(c as IActionContext); + + if (node != null) + { + ActivityNodeContextAccessor.Context.Value = c; + await node?.OnInitializeAsync(); + ActivityNodeContextAccessor.Context.Value = null; + } + }); } if (typeof(StructuredActivityNode).GetMethod(nameof(StructuredActivityNode.OnFinalizeAsync)).IsOverridenIn()) { - builder.AddOnFinalize(c => (c as BaseContext).NodeScope.GetStructuredActivity(c as IActionContext)?.OnFinalizeAsync()); + builder.AddOnFinalize(async c => + { + var node = (c as BaseContext).NodeScope.GetStructuredActivity(c as IActionContext); + + if (node != null) + { + ActivityNodeContextAccessor.Context.Value = c; + await node?.OnFinalizeAsync(); + ActivityNodeContextAccessor.Context.Value = null; + } + }); } } - public static void AddObjectTransformationFlowEvents(this IObjectFlowBuilder builder) - where TObjectTransformationFlow : TransformationFlow - where TToken : Token, new() - where TTransformedToken : Token, new() + public static void AddTransformationFlowEvents(this IObjectFlowBuilder builder) + where TTransformationFlow : TransformationFlow { - if (typeof(BaseTransformationFlow).GetProperty(nameof(BaseTransformationFlow.Weight)).IsOverridenIn()) + if (typeof(BaseTransformationFlow).GetProperty(nameof(BaseTransformationFlow.Weight)).IsOverridenIn()) { - var objectFlow = FormatterServices.GetUninitializedObject(typeof(TObjectTransformationFlow)) as TObjectTransformationFlow; + var objectFlow = FormatterServices.GetUninitializedObject(typeof(TTransformationFlow)) as TTransformationFlow; builder.SetWeight(objectFlow.Weight); } - if (typeof(BaseControlFlow).GetMethod(nameof(BaseControlFlow.GuardAsync)).IsOverridenIn()) + if (typeof(BaseControlFlow).GetMethod(nameof(BaseControlFlow.GuardAsync)).IsOverridenIn()) { - builder.AddGuard(c => (c as BaseContext).NodeScope.GetObjectTransformationFlow(c)?.GuardAsync()); + builder.AddGuard(async c => + { + var result = false; + var flow = (c as BaseContext).NodeScope.GetObjectTransformationFlow(c); + if (flow != null) + { + ActivityFlowContextAccessor.Context.Value = c; + result = await flow?.GuardAsync(); + ActivityFlowContextAccessor.Context.Value = null; + } + + return result; + }); } - if (typeof(BaseTransformationFlow).GetMethod(nameof(BaseTransformationFlow.TransformAsync)).IsOverridenIn()) + if (typeof(BaseTransformationFlow).GetMethod(nameof(BaseTransformationFlow.TransformAsync)).IsOverridenIn()) { - builder.AddTransformation(c => (c as BaseContext).NodeScope.GetObjectTransformationFlow(c)?.TransformAsync()); + builder.AddTransformation(async c => + { + TTransformedToken result = default; + var flow = (c as BaseContext).NodeScope.GetObjectTransformationFlow(c); + if (flow != null) + { + ActivityFlowContextAccessor.Context.Value = c; + result = await flow?.TransformAsync(); + ActivityFlowContextAccessor.Context.Value = null; + } + + return result; + }); } } - public static void AddObjectFlowEvents(this IObjectFlowBuilder builder) - where TObjectFlow : Flow - where TToken : Token, new() + public static void AddElseTransformationFlowEvents(this IObjectFlowBuilder builder) + where TElseTransformationFlow : ElseTransformationFlow { - if (typeof(BaseFlow).GetProperty(nameof(BaseFlow.Weight)).IsOverridenIn()) + if (typeof(BaseTransformationFlow).GetProperty(nameof(BaseTransformationFlow.Weight)).IsOverridenIn()) { - var objectFlow = FormatterServices.GetUninitializedObject(typeof(TObjectFlow)) as TObjectFlow; + var objectFlow = FormatterServices.GetUninitializedObject(typeof(TElseTransformationFlow)) as TElseTransformationFlow; builder.SetWeight(objectFlow.Weight); } - if (typeof(BaseControlFlow).GetMethod(nameof(BaseControlFlow.GuardAsync)).IsOverridenIn()) + if (typeof(BaseControlFlow).GetMethod(nameof(BaseControlFlow.GuardAsync)).IsOverridenIn()) { - builder.AddGuard(c => (c as BaseContext).NodeScope.GetObjectFlow(c)?.GuardAsync()); + builder.AddGuard(async c => + { + var result = false; + var flow = (c as BaseContext).NodeScope.GetElseObjectTransformationFlow(c); + if (flow != null) + { + ActivityFlowContextAccessor.Context.Value = c; + result = await flow?.GuardAsync(); + ActivityFlowContextAccessor.Context.Value = null; + } + + return result; + }); + } + + if (typeof(BaseTransformationFlow).GetMethod(nameof(BaseTransformationFlow.TransformAsync)).IsOverridenIn()) + { + builder.AddTransformation(async c => + { + TTransformedToken result = default; + var flow = (c as BaseContext).NodeScope.GetElseObjectTransformationFlow(c); + if (flow != null) + { + ActivityFlowContextAccessor.Context.Value = c; + result = await flow?.TransformAsync(); + ActivityFlowContextAccessor.Context.Value = null; + } + + return result; + }); + } + } + + public static void AddObjectFlowEvents(this IObjectFlowBuilder builder) + where TFlow : Flow + { + if (typeof(BaseFlow).GetProperty(nameof(BaseFlow.Weight)).IsOverridenIn()) + { + var objectFlow = FormatterServices.GetUninitializedObject(typeof(TFlow)) as TFlow; + + builder.SetWeight(objectFlow.Weight); + } + + if (typeof(BaseControlFlow).GetMethod(nameof(BaseControlFlow.GuardAsync)).IsOverridenIn()) + { + builder.AddGuard(async c => + { + var result = false; + var flow = (c as BaseContext).NodeScope.GetObjectFlow(c); + if (flow != null) + { + ActivityFlowContextAccessor.Context.Value = c; + result = await flow?.GuardAsync(); + ActivityFlowContextAccessor.Context.Value = null; + } + + return result; + }); } } @@ -110,7 +208,19 @@ public static void AddControlFlowEvents(this IControlFlowBuilder b { if (typeof(BaseControlFlow).GetMethod(nameof(BaseControlFlow.GuardAsync)).IsOverridenIn()) { - builder.AddGuard(c => (c as BaseContext).NodeScope.GetControlFlow(c)?.GuardAsync()); + builder.AddGuard(async c => + { + var result = false; + var flow = (c as BaseContext).NodeScope.GetControlFlow(c); + if (flow != null) + { + ActivityFlowContextAccessor.Context.Value = c; + result = await flow?.GuardAsync(); + ActivityFlowContextAccessor.Context.Value = null; + } + + return result; + }); } } } diff --git a/Core/Stateflows/Activities/Extensions/IEnumerableOfTokensExtensions.cs b/Core/Stateflows/Activities/Extensions/IEnumerableOfTokensExtensions.cs deleted file mode 100644 index e88fdfd1..00000000 --- a/Core/Stateflows/Activities/Extensions/IEnumerableOfTokensExtensions.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Linq; -using System.Collections.Generic; -using Stateflows.Common; - -namespace Stateflows.Activities -{ - public static class IEnumerableOfTokensExtensions - { - public static GroupToken ToGroupToken(this IEnumerable tokens) - where TToken : Token, new() - => new GroupToken() { Tokens = tokens.ToList() }; - - public static IEnumerable ToPayloads(this IEnumerable> tokens) - => tokens.Select(t => t.Payload).ToArray(); - } -} diff --git a/Core/Stateflows/Activities/Extensions/IOutputExtensions.cs b/Core/Stateflows/Activities/Extensions/IOutputExtensions.cs deleted file mode 100644 index 8276d75f..00000000 --- a/Core/Stateflows/Activities/Extensions/IOutputExtensions.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Linq; -using System.Collections.Generic; -using Stateflows.Common; -using Stateflows.Common.Data; -using Stateflows.Activities.Context.Interfaces; - -namespace Stateflows.Activities -{ - public static class IOutputExtensions - { - public static void Output(this IOutput output, TTokenPayload payload) - => output.Output(payload.ToToken()); - - public static void OutputRange(this IOutput output, IEnumerable payloads) - => output.Output(payloads.Select(payload => payload.ToToken()).ToArray()); - - public static void OutputRangeAsGroup(this IOutput output, IEnumerable payloads) - => output.OutputRangeAsGroup(payloads.Select(payload => payload.ToToken()).ToArray()); - - public static void PassTokensOfTypeOn(this IOutput output) - => output.PassTokensOfTypeOn>(); - } -} diff --git a/Core/Stateflows/Activities/Extensions/IServiceCollectionExtensions.cs b/Core/Stateflows/Activities/Extensions/IServiceCollectionExtensions.cs index 74053b75..d15f38e0 100644 --- a/Core/Stateflows/Activities/Extensions/IServiceCollectionExtensions.cs +++ b/Core/Stateflows/Activities/Extensions/IServiceCollectionExtensions.cs @@ -1,15 +1,14 @@ using System; using Microsoft.Extensions.DependencyInjection; using Stateflows.Common.Extensions; -using Stateflows.Common; namespace Stateflows.Activities.Extensions { internal static class IServiceCollectionExtensions { - public static IServiceCollection RegisterActivity(this IServiceCollection services) - where TActivity : Activity - => services?.AddServiceType(); + //public static IServiceCollection RegisterActivity(this IServiceCollection services) + // where TActivity : Activity + // => services?.AddServiceType(); public static IServiceCollection RegisterActivity(this IServiceCollection services, Type activityType) => services?.AddServiceType(activityType); @@ -27,35 +26,29 @@ public static IServiceCollection RegisterExceptionHandlerAction => services?.AddServiceType(); - public static IServiceCollection RegisterObjectFlow(this IServiceCollection services) - where TObjectFlow : Flow - where TToken : Token, new() - => services?.AddServiceType(); + public static IServiceCollection RegisterObjectFlow(this IServiceCollection services) + where TFlow : Flow + => services?.AddServiceType(); - public static IServiceCollection RegisterElseObjectFlow(this IServiceCollection services) - where TObjectFlow : ElseFlow - where TToken : Token, new() - => services?.AddServiceType(); + //public static IServiceCollection RegisterElseObjectFlow(this IServiceCollection services) + // where TFlow : ElseFlow + // => services?.AddServiceType(); - public static IServiceCollection RegisterObjectTransformationFlow(this IServiceCollection services) + public static IServiceCollection RegisterTransformationFlow(this IServiceCollection services) where TObjectTransformationFlow : TransformationFlow - where TToken : Token, new() - where TTransformedToken : Token, new() => services?.AddServiceType(); - public static IServiceCollection RegisterElseObjectTransformationFlow(this IServiceCollection services) - where TObjectTransformationFlow : ElseObjectTransformationFlow - where TToken : Token, new() - where TTransformedToken : Token, new() + public static IServiceCollection RegisterElseTransformationFlow(this IServiceCollection services) + where TObjectTransformationFlow : ElseTransformationFlow => services?.AddServiceType(); public static IServiceCollection RegisterControlFlow(this IServiceCollection services) where TControlFlow : ControlFlow => services?.AddServiceType(); - public static IServiceCollection RegisterElseControlFlow(this IServiceCollection services) - where TControlFlow : ElseControlFlow - => services?.AddServiceType(); + //public static IServiceCollection RegisterElseControlFlow(this IServiceCollection services) + // where TControlFlow : ElseControlFlow + // => services?.AddServiceType(); public static IServiceCollection RegisterObserver(this IServiceCollection services) where TObserver : class, IActivityObserver diff --git a/Core/Stateflows/Activities/Extensions/OutputExtensions.cs b/Core/Stateflows/Activities/Extensions/OutputExtensions.cs deleted file mode 100644 index 102e53c1..00000000 --- a/Core/Stateflows/Activities/Extensions/OutputExtensions.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Linq; -using System.Collections.Generic; -using Stateflows.Common; -using Stateflows.Common.Data; - -namespace Stateflows.Activities -{ - public static class OutputExtensions - { - public static void Add(this Output> output, TTokenPayload payload) - => output.Add(payload.ToToken()); - - public static void AddRange(this Output> output, IEnumerable payloads) - => output.AddRange(payloads.Select(payload => payload.ToToken()).ToArray()); - } -} diff --git a/Core/Stateflows/Activities/Inspection/Classes/FlowInspection.cs b/Core/Stateflows/Activities/Inspection/Classes/FlowInspection.cs index 15403661..f0a722b7 100644 --- a/Core/Stateflows/Activities/Inspection/Classes/FlowInspection.cs +++ b/Core/Stateflows/Activities/Inspection/Classes/FlowInspection.cs @@ -57,9 +57,9 @@ public INodeInspection Target } } - public string TokenName => TokenInfo.GetName(Edge.TokenType); + public string TokenName => Edge.TokenType.GetTokenName(); - public FlowType Type => Edge.TokenType == typeof(ControlToken) + public FlowType Type => Edge.TokenType == typeof(Control) ? FlowType.ControlFlow : FlowType.ObjectFlow; } diff --git a/Core/Stateflows/Activities/Inspection/Interfaces/IEventInspectionContext.cs b/Core/Stateflows/Activities/Inspection/Interfaces/IEventInspectionContext.cs index 00055f55..8a5be42d 100644 --- a/Core/Stateflows/Activities/Inspection/Interfaces/IEventInspectionContext.cs +++ b/Core/Stateflows/Activities/Inspection/Interfaces/IEventInspectionContext.cs @@ -4,7 +4,7 @@ namespace Stateflows.Activities.Inspection.Interfaces { public interface IEventInspectionContext : IEventContext - where TEvent : Event + where TEvent : Event, new() { new IActivityInspectionContext Activity { get; } } diff --git a/Core/Stateflows/Activities/Inspection/Interfaces/IGuardInspectionContext.cs b/Core/Stateflows/Activities/Inspection/Interfaces/IGuardInspectionContext.cs index 67a01734..3c799748 100644 --- a/Core/Stateflows/Activities/Inspection/Interfaces/IGuardInspectionContext.cs +++ b/Core/Stateflows/Activities/Inspection/Interfaces/IGuardInspectionContext.cs @@ -3,7 +3,7 @@ namespace Stateflows.Activities.Inspection.Interfaces { - public interface IGuardInspectionContext : IGuardContext + public interface IGuardInspectionContext : IGuardContext { IActivityInspection Inspection { get; } } diff --git a/Core/Stateflows/Activities/Inspection/Interfaces/ITransformationInspectionContext.cs b/Core/Stateflows/Activities/Inspection/Interfaces/ITransformationInspectionContext.cs index 816d6360..e26514bd 100644 --- a/Core/Stateflows/Activities/Inspection/Interfaces/ITransformationInspectionContext.cs +++ b/Core/Stateflows/Activities/Inspection/Interfaces/ITransformationInspectionContext.cs @@ -3,7 +3,7 @@ namespace Stateflows.Activities.Inspection.Interfaces { - public interface ITransformationInspectionContext : ITransformationContext + public interface ITransformationInspectionContext : ITransformationContext { IActivityInspection Inspection { get; } } diff --git a/Core/Stateflows/Activities/Interfaces/IActivity.cs b/Core/Stateflows/Activities/Interfaces/IActivity.cs index cae07321..b4f955e2 100644 --- a/Core/Stateflows/Activities/Interfaces/IActivity.cs +++ b/Core/Stateflows/Activities/Interfaces/IActivity.cs @@ -6,7 +6,7 @@ namespace Stateflows.Activities.Interfaces { public interface IActivity : IBehavior { - Task> Execute(IEnumerable input); + Task> Execute(IEnumerable input); Task Execute(IDictionary parameters); diff --git a/Core/Stateflows/Activities/Interfaces/IActivityExceptionHandler.cs b/Core/Stateflows/Activities/Interfaces/IActivityExceptionHandler.cs index 6ab7d930..714ba8f2 100644 --- a/Core/Stateflows/Activities/Interfaces/IActivityExceptionHandler.cs +++ b/Core/Stateflows/Activities/Interfaces/IActivityExceptionHandler.cs @@ -1,18 +1,31 @@ using System; using System.Threading.Tasks; using Stateflows.Activities.Context.Interfaces; -using Stateflows.Common; namespace Stateflows.Activities { public interface IActivityExceptionHandler { - Task OnActivityInitializationExceptionAsync(IActivityInitializationContext context, Exception exception); - Task OnActivityFinalizationExceptionAsync(IActivityFinalizationContext context, Exception exception); - Task OnNodeInitializationExceptionAsync(IActivityNodeContext context, Exception exception); - Task OnNodeFinalizationExceptionAsync(IActivityNodeContext context, Exception exception); - Task OnNodeExecutionExceptionAsync(IActivityNodeContext context, Exception exception); - Task OnFlowGuardExceptionAsync(IGuardContext context, Exception exception); - Task OnFlowTransformationExceptionAsync(ITransformationContext context, Exception exception); + Task OnActivityInitializationExceptionAsync(IActivityInitializationContext context, Exception exception) + => Task.CompletedTask; + + Task OnActivityFinalizationExceptionAsync(IActivityFinalizationContext context, Exception exception) + => Task.CompletedTask; + + Task OnNodeInitializationExceptionAsync(IActivityNodeContext context, Exception exception) + => Task.CompletedTask; + + Task OnNodeFinalizationExceptionAsync(IActivityNodeContext context, Exception exception) + => Task.CompletedTask; + + Task OnNodeExecutionExceptionAsync(IActivityNodeContext context, Exception exception) + => Task.CompletedTask; + + Task OnFlowGuardExceptionAsync(IGuardContext context, Exception exception) + => Task.CompletedTask; + + Task OnFlowTransformationExceptionAsync(ITransformationContext context, Exception exception) + => Task.CompletedTask; + } } diff --git a/Core/Stateflows/Activities/Interfaces/IActivityInspector.cs b/Core/Stateflows/Activities/Interfaces/IActivityInspector.cs index 4687c0a7..e2e0765e 100644 --- a/Core/Stateflows/Activities/Interfaces/IActivityInspector.cs +++ b/Core/Stateflows/Activities/Interfaces/IActivityInspector.cs @@ -1,38 +1,65 @@ using System; using System.Threading.Tasks; +using Stateflows.Activities.Context.Interfaces; using Stateflows.Activities.Inspection.Interfaces; namespace Stateflows.Activities { public interface IActivityInspector { - Task BeforeActivityInitializationAsync(IActivityInitializationInspectionContext context); - Task AfterActivityInitializationAsync(IActivityInitializationInspectionContext context); + Task BeforeActivityInitializeAsync(IActivityInitializationInspectionContext context) + => Task.CompletedTask; + Task AfterActivityInitializeAsync(IActivityInitializationInspectionContext context) + => Task.CompletedTask; - Task BeforeActivityFinalizationAsync(IActivityFinalizationInspectionContext context); - Task AfterActivityFinalizationAsync(IActivityFinalizationInspectionContext context); + Task BeforeActivityFinalizeAsync(IActivityFinalizationInspectionContext context) + => Task.CompletedTask; + Task AfterActivityFinalizeAsync(IActivityFinalizationInspectionContext context) + => Task.CompletedTask; - Task BeforeNodeInitializationAsync(IActivityNodeInspectionContext context); - Task AfterNodeInitializationAsync(IActivityNodeInspectionContext context); + Task BeforeNodeInitializeAsync(IActivityNodeInspectionContext context) + => Task.CompletedTask; + Task AfterNodeInitializeAsync(IActivityNodeInspectionContext context) + => Task.CompletedTask; - Task BeforeNodeFinalizationAsync(IActivityNodeInspectionContext context); - Task AfterNodeFinalizationAsync(IActivityNodeInspectionContext context); + Task BeforeNodeFinalizeAsync(IActivityNodeInspectionContext context) + => Task.CompletedTask; + Task AfterNodeFinalizeAsync(IActivityNodeInspectionContext context) + => Task.CompletedTask; - Task BeforeNodeExecuteAsync(IActivityNodeInspectionContext context); - Task AfterNodeExecuteAsync(IActivityNodeInspectionContext context); + Task BeforeNodeActivateAsync(IActivityNodeContext context, bool activated) + => Task.CompletedTask; + Task AfterNodeActivateAsync(IActivityNodeContext context) + => Task.CompletedTask; - Task BeforeFlowGuardAsync(IGuardInspectionContext context); - Task AfterFlowGuardAsync(IGuardInspectionContext context, bool guardResult); + Task BeforeNodeExecuteAsync(IActivityNodeInspectionContext context) + => Task.CompletedTask; + Task AfterNodeExecuteAsync(IActivityNodeInspectionContext context) + => Task.CompletedTask; - Task BeforeFlowTransformationAsync(ITransformationInspectionContext context); - Task AfterFlowTransformationAsync(ITransformationInspectionContext context); + Task BeforeFlowGuardAsync(IGuardInspectionContext context) + => Task.CompletedTask; + Task AfterFlowGuardAsync(IGuardInspectionContext context, bool guardResult) + => Task.CompletedTask; - Task OnActivityInitializationExceptionAsync(IActivityInitializationInspectionContext context, Exception exception); - Task OnActivityFinalizationExceptionAsync(IActivityFinalizationInspectionContext context, Exception exception); - Task OnNodeInitializationExceptionAsync(IActivityNodeInspectionContext context, Exception exception); - Task OnNodeFinalizationExceptionAsync(IActivityNodeInspectionContext context, Exception exception); - Task OnNodeExecutionExceptionAsync(IActivityNodeInspectionContext context, Exception exception); - Task OnFlowGuardExceptionAsync(IGuardInspectionContext context, Exception exception); - Task OnFlowTransformationExceptionAsync(ITransformationInspectionContext context, Exception exception); + Task BeforeFlowTransformAsync(ITransformationInspectionContext context) + => Task.CompletedTask; + Task AfterFlowTransformAsync(ITransformationInspectionContext context) + => Task.CompletedTask; + + Task OnActivityInitializationExceptionAsync(IActivityInitializationInspectionContext context, Exception exception) + => Task.CompletedTask; + Task OnActivityFinalizationExceptionAsync(IActivityFinalizationInspectionContext context, Exception exception) + => Task.CompletedTask; + Task OnNodeInitializationExceptionAsync(IActivityNodeInspectionContext context, Exception exception) + => Task.CompletedTask; + Task OnNodeFinalizationExceptionAsync(IActivityNodeInspectionContext context, Exception exception) + => Task.CompletedTask; + Task OnNodeExecutionExceptionAsync(IActivityNodeInspectionContext context, Exception exception) + => Task.CompletedTask; + Task OnFlowGuardExceptionAsync(IGuardInspectionContext context, Exception exception) + => Task.CompletedTask; + Task OnFlowTransformationExceptionAsync(ITransformationInspectionContext context, Exception exception) + => Task.CompletedTask; } } diff --git a/Core/Stateflows/Activities/Interfaces/IActivityInterceptor.cs b/Core/Stateflows/Activities/Interfaces/IActivityInterceptor.cs index 0b188488..bf453a93 100644 --- a/Core/Stateflows/Activities/Interfaces/IActivityInterceptor.cs +++ b/Core/Stateflows/Activities/Interfaces/IActivityInterceptor.cs @@ -6,9 +6,17 @@ namespace Stateflows.Activities { public interface IActivityInterceptor { - Task AfterHydrateAsync(IActivityActionContext context); - Task BeforeDehydrateAsync(IActivityActionContext context); - Task BeforeProcessEventAsync(IEventContext context); - Task AfterProcessEventAsync(IEventContext context); + Task AfterHydrateAsync(IActivityActionContext context) + => Task.CompletedTask; + + Task BeforeDehydrateAsync(IActivityActionContext context) + => Task.CompletedTask; + + Task BeforeProcessEventAsync(IEventContext context) + => Task.FromResult(true); + + Task AfterProcessEventAsync(IEventContext context) + => Task.CompletedTask; + } } diff --git a/Core/Stateflows/Activities/Interfaces/IActivityObserver.cs b/Core/Stateflows/Activities/Interfaces/IActivityObserver.cs index 84cbaa9c..555aa339 100644 --- a/Core/Stateflows/Activities/Interfaces/IActivityObserver.cs +++ b/Core/Stateflows/Activities/Interfaces/IActivityObserver.cs @@ -1,30 +1,53 @@ using System.Threading.Tasks; using Stateflows.Activities.Context.Interfaces; -using Stateflows.Common; namespace Stateflows.Activities { public interface IActivityObserver { - Task BeforeActivityInitializationAsync(IActivityInitializationContext context); - Task AfterActivityInitializationAsync(IActivityInitializationContext context); + Task BeforeActivityInitializeAsync(IActivityInitializationContext context) + => Task.CompletedTask; + Task AfterActivityInitializeAsync(IActivityInitializationContext context) + => Task.CompletedTask; - Task BeforeActivityFinalizationAsync(IActivityFinalizationContext context); - Task AfterActivityFinalizationAsync(IActivityFinalizationContext context); + Task BeforeActivityFinalizeAsync(IActivityFinalizationContext context) + => Task.CompletedTask; + Task AfterActivityFinalizeAsync(IActivityFinalizationContext context) + => Task.CompletedTask; - Task BeforeNodeInitializationAsync(IActivityNodeContext context); - Task AfterNodeInitializationAsync(IActivityNodeContext context); + Task BeforeNodeInitializeAsync(IActivityNodeContext context) + => Task.CompletedTask; + Task AfterNodeInitializeAsync(IActivityNodeContext context) + => Task.CompletedTask; - Task BeforeNodeFinalizationAsync(IActivityNodeContext context); - Task AfterNodeFinalizationAsync(IActivityNodeContext context); + Task BeforeNodeFinalizeAsync(IActivityNodeContext context) + => Task.CompletedTask; + Task AfterNodeFinalizeAsync(IActivityNodeContext context) + => Task.CompletedTask; - Task BeforeNodeExecuteAsync(IActivityNodeContext context); - Task AfterNodeExecuteAsync(IActivityNodeContext context); + Task BeforeNodeActivateAsync(IActivityNodeContext context, bool activated) + => Task.CompletedTask; + Task AfterNodeActivateAsync(IActivityNodeContext context) + => Task.CompletedTask; - Task BeforeFlowGuardAsync(IGuardContext context); - Task AfterFlowGuardAsync(IGuardContext context, bool guardResult); + Task BeforeNodeExecuteAsync(IActivityNodeContext context) + => Task.CompletedTask; + Task AfterNodeExecuteAsync(IActivityNodeContext context) + => Task.CompletedTask; - Task BeforeFlowTransformationAsync(ITransformationContext context); - Task AfterFlowTransformationAsync(ITransformationContext context); + Task BeforeFlowActivateAsync(IActivityFlowContext context, bool activated) + => Task.CompletedTask; + Task AfterFlowActivateAsync(IActivityFlowContext context) + => Task.CompletedTask; + + Task BeforeFlowGuardAsync(IGuardContext context) + => Task.CompletedTask; + Task AfterFlowGuardAsync(IGuardContext context, bool guardResult) + => Task.CompletedTask; + + Task BeforeFlowTransformAsync(ITransformationContext context) + => Task.CompletedTask; + Task AfterFlowTransformAsync(ITransformationContext context) + => Task.CompletedTask; } } diff --git a/Core/Stateflows/Activities/Interfaces/ITokensAccessor.cs b/Core/Stateflows/Activities/Interfaces/ITokensAccessor.cs new file mode 100644 index 00000000..de8f2886 --- /dev/null +++ b/Core/Stateflows/Activities/Interfaces/ITokensAccessor.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; + +namespace Stateflows.Activities.Interfaces +{ + public interface ITokensAccessor + { + public List InputTokens { get; set; } + public List OutputTokens { get; set; } + } +} diff --git a/Core/Stateflows/Activities/Models/Delegates.cs b/Core/Stateflows/Activities/Models/Delegates.cs index 30fc3d51..3688d77c 100644 --- a/Core/Stateflows/Activities/Models/Delegates.cs +++ b/Core/Stateflows/Activities/Models/Delegates.cs @@ -5,7 +5,7 @@ namespace Stateflows.Activities.Models { - internal delegate Task TokenPipelineActionAsync(TokenPipelineContext context); + internal delegate Task TokenPipelineActionAsync(TokenPipelineContext context); internal delegate Task ActivityActionAsync(IActionContext context); @@ -13,10 +13,7 @@ namespace Stateflows.Activities.Models internal delegate Task ActivityEventActionAsync(BaseContext context); - internal delegate Task GuardAsync(BaseContext context) - where TToken : Token, new(); + internal delegate Task GuardAsync(BaseContext context); - internal delegate Task TransformAsync(BaseContext context) - where TSource : Token - where TTarget : Token; + internal delegate Task TransformAsync(BaseContext context); } \ No newline at end of file diff --git a/Core/Stateflows/Activities/Models/Edge.cs b/Core/Stateflows/Activities/Models/Edge.cs index 23920454..a0905ec4 100644 --- a/Core/Stateflows/Activities/Models/Edge.cs +++ b/Core/Stateflows/Activities/Models/Edge.cs @@ -1,4 +1,5 @@ using System; +using Stateflows.Common; namespace Stateflows.Activities.Models { diff --git a/Core/Stateflows/Activities/Models/Graph.cs b/Core/Stateflows/Activities/Models/Graph.cs index b64b361f..cb7ddd54 100644 --- a/Core/Stateflows/Activities/Models/Graph.cs +++ b/Core/Stateflows/Activities/Models/Graph.cs @@ -88,7 +88,7 @@ public void Build() if (undeclaredOutgoingTokens.Any()) { - throw new NodeDefinitionException(node.Name, $"Invalid activity '{Name}': node '{node.Name}' doesn't have incoming flow with '{TokenInfo.GetName(undeclaredOutgoingTokens.First())}' tokens, outgoing flow is invalid."); + throw new NodeDefinitionException(node.Name, $"Invalid activity '{Name}': node '{node.Name}' doesn't have incoming flow with '{undeclaredOutgoingTokens.First().GetTokenName()}' tokens, outgoing flow is invalid."); } } @@ -103,17 +103,17 @@ public void Build() if (undeclaredIncomingTokens.Any()) { - throw new NodeDefinitionException(node.Name, $"Invalid activity '{Name}': action '{node.Name}' doesn't accept incoming '{TokenInfo.GetName(undeclaredIncomingTokens.First())}' tokens, incoming flow is invalid."); + throw new NodeDefinitionException(node.Name, $"Invalid activity '{Name}': action '{node.Name}' doesn't accept incoming '{undeclaredIncomingTokens.First().GetTokenName()}' tokens, incoming flow is invalid."); } if (undeclaredOutgoingTokens.Any()) { - throw new NodeDefinitionException(node.Name, $"Invalid activity '{Name}': action '{node.Name}' doesn't produce outgoing '{TokenInfo.GetName(undeclaredOutgoingTokens.First())}' tokens, outgoing flow is invalid."); + throw new NodeDefinitionException(node.Name, $"Invalid activity '{Name}': action '{node.Name}' doesn't produce outgoing '{undeclaredOutgoingTokens.First().GetTokenName()}' tokens, outgoing flow is invalid."); } if (unsatisfiedIncomingTokens.Any()) { - throw new NodeDefinitionException(node.Name, $"Invalid activity '{Name}': action '{node.Name}' requires '{TokenInfo.GetName(unsatisfiedIncomingTokens.First())}' input tokens, but there is no incoming flow with them."); + throw new NodeDefinitionException(node.Name, $"Invalid activity '{Name}': action '{node.Name}' requires '{unsatisfiedIncomingTokens.First().GetTokenName()}' input tokens, but there is no incoming flow with them."); } } } diff --git a/Core/Stateflows/Activities/Models/Node.cs b/Core/Stateflows/Activities/Models/Node.cs index 3290107b..056aa615 100644 --- a/Core/Stateflows/Activities/Models/Node.cs +++ b/Core/Stateflows/Activities/Models/Node.cs @@ -1,11 +1,14 @@ using System; using System.Linq; +using System.Reflection; using System.Threading.Tasks; using System.Collections.Generic; +using Stateflows.Utils; using Stateflows.Common; using Stateflows.Common.Models; using Stateflows.Activities.Registration; using Stateflows.Activities.Context.Classes; +using System.Xml.Linq; namespace Stateflows.Activities.Models { @@ -49,20 +52,20 @@ public Logic Action public IEnumerable GetIncomingTokenTypes() => IncomingEdges .Select(e => e.TargetTokenType) - .Where(t => t != typeof(ControlToken) && (!t.IsGenericType || t.GetGenericTypeDefinition() != typeof(ExceptionToken<>))) + .Where(t => t != typeof(Control) && t != typeof(NodeReference) && !typeof(Exception).IsAssignableFrom(t)) .Distinct(); public IEnumerable GetOutgoingTokenTypes() => Edges .Select(e => e.TokenType) - .Where(t => t != typeof(ControlToken) && (!t.IsGenericType || t.GetGenericTypeDefinition() != typeof(ExceptionToken<>))) + .Where(t => t != typeof(Control) && t != typeof(NodeReference) && !typeof(Exception).IsAssignableFrom(t)) .Distinct(); public void ScanForDeclaredTypes(Type nodeType) { DeclaredTypesSet = true; - var fields = nodeType.GetFields().Where(field => field.FieldType.IsGenericType).ToArray(); + var fields = nodeType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Where(field => field.FieldType.IsGenericType).ToArray(); InputTokenTypes = fields .Where(field => field.FieldType.GetGenericTypeDefinition() == typeof(Input<>)) @@ -161,7 +164,7 @@ public IEnumerable ExceptionHandlers .Select(e => e.Target) .Where(n => n.Type == NodeType.ExceptionHandler); - public async Task> HandleExceptionAsync(Exception exception, BaseContext context) + public async Task> HandleExceptionAsync(Exception exception, BaseContext context) { Node handler = null; var currentNode = this; @@ -194,7 +197,11 @@ public async Task> HandleExceptionAsync(Exception exception, context.Context, currentScope, handler, - new Token[] { new ExceptionToken() { Exception = exception } } + new TokenHolder[] + { + exception.ToExceptionHolder(), + new NodeReference() { Node = this }.ToTokenHolder(), + } ); await handler.Action.WhenAll(exceptionContext); @@ -202,7 +209,7 @@ public async Task> HandleExceptionAsync(Exception exception, return exceptionContext.OutputTokens; } - return new Token[0]; + return new TokenHolder[0]; } } } diff --git a/Core/Stateflows/Activities/Registration/Builders/ActivityBuilder.cs b/Core/Stateflows/Activities/Registration/Builders/ActivityBuilder.cs index b4d74bb9..d9ce9f17 100644 --- a/Core/Stateflows/Activities/Registration/Builders/ActivityBuilder.cs +++ b/Core/Stateflows/Activities/Registration/Builders/ActivityBuilder.cs @@ -206,6 +206,24 @@ public IActivityBuilder AddObserver(ActivityObserverFactory observerFactory) return this; } + + ITypedActivityBuilder IActivityUtils.AddExceptionHandler() + => AddExceptionHandler() as ITypedActivityBuilder; + + ITypedActivityBuilder IActivityUtils.AddExceptionHandler(ActivityExceptionHandlerFactory exceptionHandlerFactory) + => AddExceptionHandler(exceptionHandlerFactory) as ITypedActivityBuilder; + + ITypedActivityBuilder IActivityUtils.AddInterceptor() + => AddInterceptor() as ITypedActivityBuilder; + + ITypedActivityBuilder IActivityUtils.AddInterceptor(ActivityInterceptorFactory interceptorFactory) + => AddInterceptor(interceptorFactory) as ITypedActivityBuilder; + + ITypedActivityBuilder IActivityUtils.AddObserver() + => AddObserver() as ITypedActivityBuilder; + + ITypedActivityBuilder IActivityUtils.AddObserver(ActivityObserverFactory observerFactory) + => AddObserver(observerFactory) as ITypedActivityBuilder; #endregion } } diff --git a/Core/Stateflows/Activities/Registration/Builders/BaseActivityBuilder.cs b/Core/Stateflows/Activities/Registration/Builders/BaseActivityBuilder.cs index cb051292..73acbbf1 100644 --- a/Core/Stateflows/Activities/Registration/Builders/BaseActivityBuilder.cs +++ b/Core/Stateflows/Activities/Registration/Builders/BaseActivityBuilder.cs @@ -103,22 +103,19 @@ public BaseActivityBuilder AddNode(NodeType type, string nodeName, ActionDelegat { try { - var observer = c.Activity.GetExecutor().Inspector; - await observer.BeforeNodeExecuteAsync(c as ActionContext); + var inspector = c.Activity.GetExecutor().Inspector; + await inspector.BeforeNodeExecuteAsync(c as ActionContext); await actionAsync(c); - await observer.AfterNodeExecuteAsync(c as ActionContext); + await inspector.AfterNodeExecuteAsync(c as ActionContext); if (!(c as BaseContext).Context.Executor.StructuralTypes.Contains(node.Type)) { - c.Output(new ControlToken()); + c.Output(new Control()); } } catch (Exception e) { await (c as BaseContext).Context.Executor.HandleExceptionAsync(node, e, c as BaseContext); - //c.OutputRange( - //await node.HandleExceptionAsync(e, c as BaseContext); - //); } } ); @@ -199,7 +196,7 @@ public BaseActivityBuilder AddInput(InputBuildAction buildAction) $"{nameof(NodeType.Input)}Node", c => { - c.PassAllOn(); + c.PassAllTokensOn(); return Task.CompletedTask; }, b => buildAction(b) @@ -211,7 +208,7 @@ public BaseActivityBuilder AddOutput() OutputNode.Name, c => { - c.PassAllOn(); + c.PassAllTokensOn(); return Task.CompletedTask; }, b => b.SetOptions(NodeOptions.None) @@ -225,15 +222,16 @@ public BaseActivityBuilder AddStructuredActivity(string structuredActivityNodeNa { var executor = c.Activity.GetContext().Executor; var node = c.GetNode(); + var contextObj = c as ActionContext; - if (!(c as ActionContext).Context.NodesToExecute.Contains(node)) + if (!contextObj.Context.NodesToExecute.Contains(node)) { await executor.DoInitializeNodeAsync(node, c as ActionContext); } - (var output, var finalized) = await executor.DoExecuteStructuredNodeAsync(node, c.Activity.GetNodeScope(), c.Input); + (var output, var finalized) = await executor.DoExecuteStructuredNodeAsync(node, c.Activity.GetNodeScope(), contextObj.InputTokens); - c.OutputRange(output); + contextObj.OutputTokens.AddRange(output); if (finalized) { @@ -244,7 +242,6 @@ public BaseActivityBuilder AddStructuredActivity(string structuredActivityNodeNa ); public BaseActivityBuilder AddParallelActivity(string parallelActivityNodeName, ParallelActivityBuildAction buildAction = null, int chunkSize = 1) - where TToken : Token, new() => AddNode( NodeType.ParallelActivity, parallelActivityNodeName, @@ -254,7 +251,7 @@ public BaseActivityBuilder AddParallelActivity(string parallelActivityNo var node = c.GetNode(); await executor.DoInitializeNodeAsync(node, c as ActionContext); - c.OutputRange(await executor.DoExecuteParallelNodeAsync(node, c.Activity.GetNodeScope(), c.Input)); + c.OutputRange(await executor.DoExecuteParallelNodeAsync(node, c.Activity.GetNodeScope(), (c as ActionContext).InputTokens)); await executor.DoFinalizeNodeAsync(node, c as ActionContext); }, b => buildAction?.Invoke(new StructuredActivityBuilder(b.Node, this, Services)), @@ -263,7 +260,6 @@ public BaseActivityBuilder AddParallelActivity(string parallelActivityNo ); public BaseActivityBuilder AddIterativeActivity(string parallelActivityNodeName, IterativeActivityBuildAction buildAction = null, int chunkSize = 1) - where TToken : Token, new() => AddNode( NodeType.IterativeActivity, parallelActivityNodeName, diff --git a/Core/Stateflows/Activities/Registration/Builders/DecisionBuilder.cs b/Core/Stateflows/Activities/Registration/Builders/DecisionBuilder.cs index a35bfdb4..d6bfbd38 100644 --- a/Core/Stateflows/Activities/Registration/Builders/DecisionBuilder.cs +++ b/Core/Stateflows/Activities/Registration/Builders/DecisionBuilder.cs @@ -1,10 +1,8 @@ -using Stateflows.Common; -using Stateflows.Activities.Registration.Interfaces; +using Stateflows.Activities.Registration.Interfaces; namespace Stateflows.Activities.Registration.Builders { internal class DecisionBuilder : NodeBuilder, IDecisionBuilder - where TToken : Token, new() { public DecisionBuilder(NodeBuilder builder) : base(builder.Node, builder.ActivityBuilder, builder.Services) diff --git a/Core/Stateflows/Activities/Registration/Builders/FlowBuilder.cs b/Core/Stateflows/Activities/Registration/Builders/FlowBuilder.cs index 71fcb7df..472bc5c6 100644 --- a/Core/Stateflows/Activities/Registration/Builders/FlowBuilder.cs +++ b/Core/Stateflows/Activities/Registration/Builders/FlowBuilder.cs @@ -4,7 +4,7 @@ using Stateflows.Activities.Context.Classes; using Stateflows.Activities.Context.Interfaces; using Stateflows.Activities.Registration.Interfaces; -using Stateflows.Common; +using Stateflows.Utils; namespace Stateflows.Activities.Registration.Builders { @@ -16,7 +16,6 @@ internal class FlowBuilder : IControlFlowBuilder, IControlFlowBuilderWithWeight, IElseControlFlowBuilder - where TToken : Token, new() { public Edge Edge { get; set; } @@ -37,16 +36,16 @@ public IObjectFlowBuilder AddGuard(GuardDelegateAsync guardAsync try { return - context.Token is TToken token && - await guardAsync(new TokenFlowContext(context, token)) + context.Token is TokenHolder token && + await guardAsync(new TokenFlowContext(context, token.Payload)) ? token - : null; + : default; } catch (Exception e) { - if (Edge.Source.Parent != null) + if (Edge.Source != null) { - await Edge.Source.Parent.HandleExceptionAsync(e, context); + await Edge.Source.HandleExceptionAsync(e, context); } return null; @@ -59,7 +58,6 @@ await guardAsync(new TokenFlowContext(context, token)) } public IObjectFlowBuilder AddTransformation(TransformationDelegateAsync transformationAsync) - where TTransformedToken : Token, new() { var logic = new Logic() { @@ -71,15 +69,15 @@ public IObjectFlowBuilder AddTransformation(context, token)) - : null; + context.Token is TokenHolder token + ? (await transformationAsync(new TokenFlowContext(context, token.Payload))).ToTokenHolder() + : default; } catch (Exception e) { - if (Edge.Source.Parent != null) + if (Edge.Source != null) { - await Edge.Source.Parent.HandleExceptionAsync(e, context as BaseContext); + await Edge.Source.HandleExceptionAsync(e, context); } return null; diff --git a/Core/Stateflows/Activities/Registration/Builders/NodeBuilder.cs b/Core/Stateflows/Activities/Registration/Builders/NodeBuilder.cs index 0d7f100f..eb64f62d 100644 --- a/Core/Stateflows/Activities/Registration/Builders/NodeBuilder.cs +++ b/Core/Stateflows/Activities/Registration/Builders/NodeBuilder.cs @@ -1,8 +1,7 @@ using System; -using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; -using Stateflows.Common; using Stateflows.Activities.Models; using Stateflows.Activities.Context.Classes; using Stateflows.Activities.Registration.Builders; @@ -42,21 +41,18 @@ public NodeBuilder(Node node, BaseActivityBuilder activityBuilder, IServiceColle } public IActionBuilder AddControlFlow(string targetNodeName, ControlFlowBuildAction buildAction = null) - => AddDataFlowInternal(targetNodeName, false, b => buildAction?.Invoke(b as IControlFlowBuilder)); + => AddFlowInternal(targetNodeName, false, b => buildAction?.Invoke(b as IControlFlowBuilder)); public IActionBuilder AddElseControlFlow(string targetNodeName, ElseControlFlowBuildAction buildAction = null) - => AddDataFlowInternal(targetNodeName, true, b => buildAction?.Invoke(b as IElseControlFlowBuilder)); + => AddFlowInternal(targetNodeName, true, b => buildAction?.Invoke(b as IElseControlFlowBuilder)); public IActionBuilder AddFlow(string targetNodeName, ObjectFlowBuildAction buildAction = null) - where TToken : Token, new() - => AddDataFlowInternal(targetNodeName, false, buildAction); + => AddFlowInternal(targetNodeName, false, buildAction); public IActionBuilder AddElseFlow(string targetNodeName, ElseObjectFlowBuildAction buildAction = null) - where TToken : Token, new() - => AddDataFlowInternal(targetNodeName, true, b => buildAction?.Invoke(b as IElseObjectFlowBuilder)); + => AddFlowInternal(targetNodeName, true, b => buildAction?.Invoke(b as IElseObjectFlowBuilder)); - public IActionBuilder AddDataFlowInternal(string targetNodeName, bool isElse, ObjectFlowBuildAction buildAction = null) - where TToken : Token, new() + public IActionBuilder AddFlowInternal(string targetNodeName, bool isElse, ObjectFlowBuildAction buildAction = null) { if (Node.Parent.Type != NodeType.Activity) { @@ -109,18 +105,21 @@ public IActionBuilderWithOptions AddExceptionHandler(ExceptionHandle { var targetNodeName = $"{Node.Name}.{typeof(TException).FullName}.ExceptionHandler"; - AddFlow>(targetNodeName); + AddFlow(targetNodeName); + AddFlow(targetNodeName); + ActivityBuilder.AddNode( NodeType.ExceptionHandler, targetNodeName, (ActionDelegateAsync)(c => { var contextObj = c as ActionContext; - var context = new ExceptionHandlerContext(contextObj, Node); + var nodeOfOrigin = contextObj.InputTokens.OfType>().FirstOrDefault()?.Payload?.Node; + var context = new ExceptionHandlerContext(contextObj, Node, nodeOfOrigin, contextObj.NodeScope); exceptionHandler?.Invoke(context); - c.OutputRange((IEnumerable)context.OutputTokens); + contextObj.OutputTokens.AddRange(context.OutputTokens); return Task.CompletedTask; }), diff --git a/Core/Stateflows/Activities/Registration/Builders/StructuredActivityBuilder.cs b/Core/Stateflows/Activities/Registration/Builders/StructuredActivityBuilder.cs index 8a4b4bf7..e10c42ab 100644 --- a/Core/Stateflows/Activities/Registration/Builders/StructuredActivityBuilder.cs +++ b/Core/Stateflows/Activities/Registration/Builders/StructuredActivityBuilder.cs @@ -5,7 +5,6 @@ using Stateflows.Activities.Context.Interfaces; using Stateflows.Activities.Registration.Interfaces; using Stateflows.Activities.Registration.Interfaces.Base; -using Stateflows.Common; namespace Stateflows.Activities.Registration.Builders { @@ -28,7 +27,6 @@ public StructuredActivityBuilder(Node parentNode, BaseActivityBuilder parentActi } public IActionBuilder AddFlow(string targetNodeName, ObjectFlowBuildAction buildAction = null) - where TToken : Token, new() { NodeBuilder.AddFlow(targetNodeName, buildAction); @@ -36,7 +34,6 @@ public IActionBuilder AddFlow(string targetNodeName, ObjectFlowBuildActi } public IActionBuilder AddElseFlow(string targetNodeName, ElseObjectFlowBuildAction buildAction = null) - where TToken : Token, new() { NodeBuilder.AddElseFlow(targetNodeName, buildAction); diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Base/IActivity.cs b/Core/Stateflows/Activities/Registration/Interfaces/Base/IActivity.cs index e495a669..c1b8a825 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Base/IActivity.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Base/IActivity.cs @@ -8,10 +8,8 @@ public interface IActivity TReturn AddStructuredActivity(string actionNodeName, StructuredActivityBuildAction buildAction); - TReturn AddParallelActivity(string actionNodeName, ParallelActivityBuildAction buildAction) - where TToken : Token, new(); + TReturn AddParallelActivity(string actionNodeName, ParallelActivityBuildAction buildAction); - TReturn AddIterativeActivity(string actionNodeName, IterativeActivityBuildAction buildAction) - where TToken : Token, new(); + TReturn AddIterativeActivity(string actionNodeName, IterativeActivityBuildAction buildAction); } } diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Base/IActivityUtils.cs b/Core/Stateflows/Activities/Registration/Interfaces/Base/IActivityUtils.cs new file mode 100644 index 00000000..9320f0f0 --- /dev/null +++ b/Core/Stateflows/Activities/Registration/Interfaces/Base/IActivityUtils.cs @@ -0,0 +1,20 @@ +namespace Stateflows.Activities.Registration.Interfaces.Base +{ + public interface IActivityUtils + { + TReturn AddInterceptor(ActivityInterceptorFactory interceptorFactory); + + TReturn AddInterceptor() + where TInterceptor : class, IActivityInterceptor; + + TReturn AddObserver(ActivityObserverFactory observerFactory); + + TReturn AddObserver() + where TObserver : class, IActivityObserver; + + TReturn AddExceptionHandler(ActivityExceptionHandlerFactory exceptionHandlerFactory); + + TReturn AddExceptionHandler() + where TExceptionHandler : class, IActivityExceptionHandler; + } +} diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Base/IObjectFlow.cs b/Core/Stateflows/Activities/Registration/Interfaces/Base/IObjectFlow.cs index ec015db2..122a46d4 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Base/IObjectFlow.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Base/IObjectFlow.cs @@ -1,34 +1,101 @@ -using Stateflows.Common; +using Stateflows.Activities.Extensions; namespace Stateflows.Activities.Registration.Interfaces.Base { public interface IObjectFlow { - TReturn AddFlow(string targetNodeName, ObjectFlowBuildAction buildAction = null) - where TToken : Token, new(); + TReturn AddFlow(string targetNodeName, ObjectFlowBuildAction buildAction = null); } public interface IElseObjectFlow { - TReturn AddElseFlow(string targetNodeName, ElseObjectFlowBuildAction buildAction = null) - where TToken : Token, new(); + TReturn AddElseFlow(string targetNodeName, ElseObjectFlowBuildAction buildAction = null); } - public interface IDecisionFlow - where TToken : Token, new() + public interface IDecisionFlow { TReturn AddFlow(string targetNodeName, ObjectFlowBuildAction buildAction = null); + + TReturn AddFlow(ObjectFlowBuildAction buildAction = null) + where TTargetNode : ActivityNode + => AddFlow(ActivityNodeInfo.Name, buildAction); + + TReturn AddFlow(string targetNodeName) + where TFlow : Flow + { + (this as IInternal).Services.RegisterObjectFlow(); + + return AddFlow( + targetNodeName, + b => b.AddObjectFlowEvents() + ); + } + + TReturn AddFlow() + where TFlow : Flow + where TTargetNode : ActivityNode + => AddFlow(ActivityNodeInfo.Name); + + TReturn AddFlow(string targetNodeName) + where TTransformationFlow : TransformationFlow + { + (this as IInternal).Services.RegisterTransformationFlow(); + + return AddFlow( + targetNodeName, + b => b.AddTransformationFlowEvents() + ); + } + + TReturn AddFlow() + where TTransformationFlow : TransformationFlow + where TTargetNode : ActivityNode + => AddFlow(ActivityNodeInfo.Name); } - public interface IElseDecisionFlow - where TToken : Token, new() + public interface IElseDecisionFlow { TReturn AddElseFlow(string targetNodeName, ElseObjectFlowBuildAction buildAction = null); + + TReturn AddElseFlow(ObjectFlowBuildAction buildAction = null) + where TTargetNode : ActivityNode + => AddElseFlow(ActivityNodeInfo.Name, b => buildAction?.Invoke(b as IObjectFlowBuilder)); + + //TReturn AddElseFlow(string targetNodeName) + // where TFlow : Flow + //{ + // (this as IInternal).Services.RegisterObjectFlow(); + + // return AddElseFlow( + // targetNodeName, + // b => (b as IObjectFlowBuilder).AddObjectFlowEvents() + // ); + //} + + //TReturn AddElseFlow() + // where TFlow : Flow + // where TTargetNode : ActivityNode + // => AddElseFlow(ActivityNodeInfo.Name); + + TReturn AddElseFlow(string targetNodeName) + where TElseTransformationFlow : ElseTransformationFlow + { + (this as IInternal).Services.RegisterElseTransformationFlow(); + + return AddElseFlow( + targetNodeName, + b => (b as IObjectFlowBuilder).AddElseTransformationFlowEvents() + ); + } + + TReturn AddElseFlow() + where TElseTransformationFlow : ElseTransformationFlow + where TTargetNode : ActivityNode + => AddElseFlow(ActivityNodeInfo.Name); } public interface IObjectFlow { - void AddFlow(string targetNodeName, ObjectFlowBuildAction buildAction = null) - where TToken : Token, new(); + void AddFlow(string targetNodeName, ObjectFlowBuildAction buildAction = null); } } diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Base/IReactiveActivity.cs b/Core/Stateflows/Activities/Registration/Interfaces/Base/IReactiveActivity.cs index 7e7a0d89..16c23dea 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Base/IReactiveActivity.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Base/IReactiveActivity.cs @@ -1,6 +1,4 @@ -using Stateflows.Common; - -namespace Stateflows.Activities.Registration.Interfaces.Base +namespace Stateflows.Activities.Registration.Interfaces.Base { public interface IReactiveActivity { @@ -8,10 +6,8 @@ public interface IReactiveActivity TReturn AddStructuredActivity(string actionNodeName, ReactiveStructuredActivityBuildAction buildAction); - TReturn AddParallelActivity(string actionNodeName, ParallelActivityBuildAction buildAction, int chunkSize = 1) - where TParallelizationToken : Token, new(); + TReturn AddParallelActivity(string actionNodeName, ParallelActivityBuildAction buildAction, int chunkSize = 1); - TReturn AddIterativeActivity(string actionNodeName, IterativeActivityBuildAction buildAction, int chunkSize = 1) - where TIterationToken : Token, new(); + TReturn AddIterativeActivity(string actionNodeName, IterativeActivityBuildAction buildAction, int chunkSize = 1); } } diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Delegates.cs b/Core/Stateflows/Activities/Registration/Interfaces/Delegates.cs index 693f72c1..82a916ed 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Delegates.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Delegates.cs @@ -7,14 +7,11 @@ namespace Stateflows.Activities.Registration.Interfaces { public delegate void ActivitiesBuildAction(IActivitiesBuilder builder); - public delegate Task GuardDelegateAsync(IGuardContext context) - where TToken : Token, new(); + public delegate Task GuardDelegateAsync(IGuardContext context); public delegate Task GuardDelegateAsync(IGuardContext context); - public delegate Task TransformationDelegateAsync(ITransformationContext context) - where TSourceToken : Token, new() - where TTargetToken : Token, new(); + public delegate Task TransformationDelegateAsync(ITransformationContext context); public delegate Task ActionDelegateAsync(IActionContext context); @@ -34,11 +31,9 @@ public delegate Task AcceptEventActionDelegateAsync(IAcceptEventActio public delegate bool DecisionDelegate(IActionContext context); - public delegate void ObjectFlowBuildAction(IObjectFlowBuilder builder) - where TToken : Token, new(); + public delegate void ObjectFlowBuildAction(IObjectFlowBuilder builder); - public delegate void ElseObjectFlowBuildAction(IElseObjectFlowBuilder builder) - where TToken : Token, new(); + public delegate void ElseObjectFlowBuildAction(IElseObjectFlowBuilder builder); public delegate void ControlFlowBuildAction(IControlFlowBuilder builder); @@ -72,8 +67,7 @@ public delegate void ElseObjectFlowBuildAction(IElseObjectFlowBuilder public delegate void DecisionBuildAction(IDecisionBuilder builder); - public delegate void DecisionBuildAction(IDecisionBuilder builder) - where TToken : Token, new(); + public delegate void DecisionBuildAction(IDecisionBuilder builder); public delegate void DataStoreBuildAction(IDataStoreBuilder builder); diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/AcceptEventActionBuilder/AcceptEventActionBuilderExceptionHandlersExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/AcceptEventActionBuilder/AcceptEventActionBuilderExceptionHandlersExtensions.cs index 1788a3ad..07bc2609 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/AcceptEventActionBuilder/AcceptEventActionBuilderExceptionHandlersExtensions.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/AcceptEventActionBuilder/AcceptEventActionBuilderExceptionHandlersExtensions.cs @@ -13,7 +13,17 @@ public static IAcceptEventActionBuilder AddExceptionHandler(); - return builder.AddExceptionHandler(c => (c as BaseContext).NodeScope.GetExceptionHandler(c).HandleAsync()); + return builder.AddExceptionHandler(async c => + { + var handler = (c as BaseContext).NodeScope.GetExceptionHandler(c); + + if (handler != null) + { + ActivityNodeContextAccessor.Context.Value = c; + await handler?.HandleAsync(); + ActivityNodeContextAccessor.Context.Value = null; + } + }); } } } diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/AcceptEventActionBuilder/Flows/AcceptEventActionBuilderObjectFlowsPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/AcceptEventActionBuilder/Flows/AcceptEventActionBuilderObjectFlowsPayloadExtensions.cs deleted file mode 100644 index 282a8ec3..00000000 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/AcceptEventActionBuilder/Flows/AcceptEventActionBuilderObjectFlowsPayloadExtensions.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Stateflows.Common; -using Stateflows.Activities.Registration.Interfaces; - -namespace Stateflows.Activities.Data -{ - public static class AcceptEventActionBuilderObjectFlowsPayloadExtensions - { - public static IAcceptEventActionBuilder AddDataFlow(this IAcceptEventActionBuilder builder, string targetNodeName, ObjectFlowBuildAction> buildAction = null) - => builder.AddFlow>(targetNodeName, buildAction); - } -} diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/AcceptEventActionBuilder/Flows/AcceptEventActionBuilderObjectFlowsTypedExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/AcceptEventActionBuilder/Flows/AcceptEventActionBuilderObjectFlowsTypedExtensions.cs index b5afb4b2..d93a345d 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/AcceptEventActionBuilder/Flows/AcceptEventActionBuilderObjectFlowsTypedExtensions.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/AcceptEventActionBuilder/Flows/AcceptEventActionBuilderObjectFlowsTypedExtensions.cs @@ -1,5 +1,4 @@ -using Stateflows.Common; -using Stateflows.Activities.Extensions; +using Stateflows.Activities.Extensions; using Stateflows.Activities.Registration.Interfaces; namespace Stateflows.Activities.Typed @@ -7,46 +6,39 @@ namespace Stateflows.Activities.Typed public static class AcceptEventActionBuilderObjectFlowsTypedExtensions { public static IAcceptEventActionBuilder AddFlow(this IAcceptEventActionBuilder builder, ObjectFlowBuildAction buildAction = null) - where TToken : Token, new() where TTargetNode : ActivityNode => builder.AddFlow(ActivityNodeInfo.Name, buildAction); - public static IAcceptEventActionBuilder AddFlow(this IAcceptEventActionBuilder builder, string targetNodeName) - where TToken : Token, new() - where TObjectFlow : Flow + public static IAcceptEventActionBuilder AddFlow(this IAcceptEventActionBuilder builder, string targetNodeName) + where TFlow : Flow { - (builder as IInternal).Services.RegisterObjectFlow(); + (builder as IInternal).Services.RegisterObjectFlow(); return builder.AddFlow( targetNodeName, - b => b.AddObjectFlowEvents() + b => b.AddObjectFlowEvents() ); } - public static IAcceptEventActionBuilder AddFlow(this IAcceptEventActionBuilder builder) - where TToken : Token, new() - where TObjectFlow : Flow + public static IAcceptEventActionBuilder AddFlow(this IAcceptEventActionBuilder builder) + where TFlow : Flow where TTargetNode : ActivityNode - => builder.AddFlow(ActivityNodeInfo.Name); + => builder.AddFlow(ActivityNodeInfo.Name); - public static IAcceptEventActionBuilder AddFlow(this IAcceptEventActionBuilder builder, string targetNodeName) - where TToken : Token, new() - where TTransformedToken : Token, new() - where TObjectTransformationFlow : TransformationFlow + public static IAcceptEventActionBuilder AddFlow(this IAcceptEventActionBuilder builder, string targetNodeName) + where TTransformationFlow : TransformationFlow { - (builder as IInternal).Services.RegisterObjectTransformationFlow(); + (builder as IInternal).Services.RegisterTransformationFlow(); return builder.AddFlow( targetNodeName, - b => b.AddObjectTransformationFlowEvents() + b => b.AddTransformationFlowEvents() ); } - public static IAcceptEventActionBuilder AddFlow(this IAcceptEventActionBuilder builder) - where TToken : Token, new() - where TTransformedToken : Token, new() - where TObjectTransformationFlow : TransformationFlow + public static IAcceptEventActionBuilder AddFlow(this IAcceptEventActionBuilder builder) + where TTransformationFlow : TransformationFlow where TTargetNode : ActivityNode - => builder.AddFlow(ActivityNodeInfo.Name); + => builder.AddFlow(ActivityNodeInfo.Name); } } diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/AcceptEventActionBuilder/Flows/AcceptEventActionBuilderObjectFlowsTypedPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/AcceptEventActionBuilder/Flows/AcceptEventActionBuilderObjectFlowsTypedPayloadExtensions.cs deleted file mode 100644 index d6e6f65c..00000000 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/AcceptEventActionBuilder/Flows/AcceptEventActionBuilderObjectFlowsTypedPayloadExtensions.cs +++ /dev/null @@ -1,46 +0,0 @@ -using Stateflows.Common; -using Stateflows.Activities.Data; -using Stateflows.Activities.Extensions; -using Stateflows.Activities.Registration.Interfaces; - -namespace Stateflows.Activities.Typed.Data -{ - public static class AcceptEventActionBuilderObjectFlowsTypedPayloadExtensions - { - public static IAcceptEventActionBuilder AddDataFlow(this IAcceptEventActionBuilder builder, ObjectFlowBuildAction> buildAction = null) - where TTargetNode : ActivityNode - => builder.AddDataFlow(ActivityNodeInfo.Name, buildAction); - - public static IAcceptEventActionBuilder AddDataFlow(this IAcceptEventActionBuilder builder, string targetNodeName) - where TObjectFlow : Flow> - { - (builder as IInternal).Services.RegisterObjectFlow>(); - - return builder.AddFlow>( - targetNodeName, - b => b.AddObjectFlowEvents>() - ); - } - - public static IAcceptEventActionBuilder AddDataFlow(this IAcceptEventActionBuilder builder) - where TObjectFlow : Flow> - where TTargetNode : ActivityNode - => builder.AddDataFlow(ActivityNodeInfo.Name); - - public static IAcceptEventActionBuilder AddDataFlow(this IAcceptEventActionBuilder builder, string targetNodeName) - where TObjectTransformationFlow : TransformationFlow, Token> - { - (builder as IInternal).Services.RegisterObjectTransformationFlow, Token>(); - - return builder.AddFlow>( - targetNodeName, - b => b.AddObjectTransformationFlowEvents, Token>() - ); - } - - public static IAcceptEventActionBuilder AddDataFlow(this IAcceptEventActionBuilder builder) - where TObjectTransformationFlow : TransformationFlow, Token> - where TTargetNode : ActivityNode - => builder.AddFlow, Token, TObjectTransformationFlow>(ActivityNodeInfo.Name); - } -} diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActionBuilder/ActionBuilderExceptionHandlersExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActionBuilder/ActionBuilderExceptionHandlersExtensions.cs index 64aa06a6..e53fe882 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActionBuilder/ActionBuilderExceptionHandlersExtensions.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActionBuilder/ActionBuilderExceptionHandlersExtensions.cs @@ -13,7 +13,17 @@ public static IActionBuilder AddExceptionHandler( { (builder as IInternal).Services.RegisterExceptionHandlerAction(); - return builder.AddExceptionHandler(c => (c as BaseContext).NodeScope.GetExceptionHandler(c).HandleAsync()); + return builder.AddExceptionHandler(async c => + { + var handler = (c as BaseContext).NodeScope.GetExceptionHandler(c); + + if (handler != null) + { + ActivityNodeContextAccessor.Context.Value = c; + await handler?.HandleAsync(); + ActivityNodeContextAccessor.Context.Value = null; + } + }); } } } diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActionBuilder/Flows/ActionBuilderObjectFlowsPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActionBuilder/Flows/ActionBuilderObjectFlowsPayloadExtensions.cs deleted file mode 100644 index a27f00fa..00000000 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActionBuilder/Flows/ActionBuilderObjectFlowsPayloadExtensions.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Stateflows.Common; -using Stateflows.Activities.Registration.Interfaces; - -namespace Stateflows.Activities.Data -{ - public static class ActionBuilderObjectFlowsPayloadExtensions - { - public static IActionBuilder AddDataFlow(this IActionBuilder builder, string targetNodeName, ObjectFlowBuildAction> buildAction = null) - => builder.AddFlow>(targetNodeName, buildAction); - } -} diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActionBuilder/Flows/ActionBuilderObjectFlowsTypedExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActionBuilder/Flows/ActionBuilderObjectFlowsTypedExtensions.cs index da152c16..30131a1e 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActionBuilder/Flows/ActionBuilderObjectFlowsTypedExtensions.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActionBuilder/Flows/ActionBuilderObjectFlowsTypedExtensions.cs @@ -7,44 +7,37 @@ namespace Stateflows.Activities.Typed public static class ActionBuilderObjectFlowsTypedExtensions { public static IActionBuilder AddFlow(this IActionBuilder builder, ObjectFlowBuildAction buildAction = null) - where TToken : Token, new() where TTargetNode : ActivityNode => builder.AddFlow(ActivityNodeInfo.Name, buildAction); - public static IActionBuilder AddFlow(this IActionBuilder builder, string targetNodeName) - where TToken : Token, new() - where TObjectFlow : Flow + public static IActionBuilder AddFlow(this IActionBuilder builder, string targetNodeName) + where TFlow : Flow { - (builder as IInternal).Services.RegisterObjectFlow(); + (builder as IInternal).Services.RegisterObjectFlow(); return builder.AddFlow( targetNodeName, - b => b.AddObjectFlowEvents() + b => b.AddObjectFlowEvents() ); } - public static IActionBuilder AddFlow(this IActionBuilder builder) - where TToken : Token, new() - where TObjectFlow : Flow + public static IActionBuilder AddFlow(this IActionBuilder builder) + where TFlow : Flow where TTargetNode : ActivityNode - => builder.AddFlow(ActivityNodeInfo.Name); + => builder.AddFlow(ActivityNodeInfo.Name); public static IActionBuilder AddFlow(this IActionBuilder builder, string targetNodeName) - where TToken : Token, new() - where TTransformedToken : Token, new() where TObjectTransformationFlow : TransformationFlow { - (builder as IInternal).Services.RegisterObjectTransformationFlow(); + (builder as IInternal).Services.RegisterTransformationFlow(); return builder.AddFlow( targetNodeName, - b => b.AddObjectTransformationFlowEvents() + b => b.AddTransformationFlowEvents() ); } public static IActionBuilder AddFlow(this IActionBuilder builder) - where TToken : Token, new() - where TTransformedToken : Token, new() where TObjectTransformationFlow : TransformationFlow where TTargetNode : ActivityNode => builder.AddFlow(ActivityNodeInfo.Name); diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActionBuilder/Flows/ActionBuilderObjectFlowsTypedPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActionBuilder/Flows/ActionBuilderObjectFlowsTypedPayloadExtensions.cs deleted file mode 100644 index 55247d2c..00000000 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActionBuilder/Flows/ActionBuilderObjectFlowsTypedPayloadExtensions.cs +++ /dev/null @@ -1,46 +0,0 @@ -using Stateflows.Common; -using Stateflows.Activities.Data; -using Stateflows.Activities.Extensions; -using Stateflows.Activities.Registration.Interfaces; - -namespace Stateflows.Activities.Typed.Data -{ - public static class ActionBuilderObjectFlowsTypedPayloadExtensions - { - public static IActionBuilder AddDataFlow(this IActionBuilder builder, ObjectFlowBuildAction> buildAction = null) - where TTargetNode : ActivityNode - => builder.AddDataFlow(ActivityNodeInfo.Name, buildAction); - - public static IActionBuilder AddDataFlow(this IActionBuilder builder, string targetNodeName) - where TObjectFlow : Flow> - { - (builder as IInternal).Services.RegisterObjectFlow>(); - - return builder.AddFlow>( - targetNodeName, - b => b.AddObjectFlowEvents>() - ); - } - - public static IActionBuilder AddDataFlow(this IActionBuilder builder) - where TObjectFlow : Flow> - where TTargetNode : ActivityNode - => builder.AddDataFlow(ActivityNodeInfo.Name); - - public static IActionBuilder AddDataFlow(this IActionBuilder builder, string targetNodeName) - where TObjectTransformationFlow : TransformationFlow, Token> - { - (builder as IInternal).Services.RegisterObjectTransformationFlow, Token>(); - - return builder.AddFlow>( - targetNodeName, - b => b.AddObjectTransformationFlowEvents, Token>() - ); - } - - public static IActionBuilder AddDataFlow(this IActionBuilder builder) - where TObjectTransformationFlow : TransformationFlow, Token> - where TTargetNode : ActivityNode - => builder.AddFlow, Token, TObjectTransformationFlow>(ActivityNodeInfo.Name); - } -} diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActivityBuilder/ActivityBuilderAnonymousExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActivityBuilder/ActivityBuilderAnonymousExtensions.cs index 95030cbc..7927f4ae 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActivityBuilder/ActivityBuilderAnonymousExtensions.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActivityBuilder/ActivityBuilderAnonymousExtensions.cs @@ -9,11 +9,9 @@ public static IActivityBuilder AddStructuredActivity(this IActivityBuilder build => builder.AddStructuredActivity(ActivityNodeInfo.Name, buildAction); public static IActivityBuilder AddParallelActivity(this IActivityBuilder builder, ParallelActivityBuildAction buildAction, int chunkSize = 1) - where TParallelizationToken : Token, new() => builder.AddParallelActivity(ActivityNodeInfo>.Name, buildAction, chunkSize); public static IActivityBuilder AddIterativeActivity(this IActivityBuilder builder, IterativeActivityBuildAction buildAction, int chunkSize = 1) - where TIterationToken : Token, new() => builder.AddIterativeActivity(ActivityNodeInfo>.Name, buildAction, chunkSize); } } diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActivityBuilder/ActivityBuilderSpecialsExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActivityBuilder/ActivityBuilderSpecialsExtensions.cs index 4ece3c00..4a1d8529 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActivityBuilder/ActivityBuilderSpecialsExtensions.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActivityBuilder/ActivityBuilderSpecialsExtensions.cs @@ -15,7 +15,7 @@ public static IActivityBuilder AddJoin(this IActivityBuilder builder, string joi joinNodeName, c => { - c.PassAllOn(); + c.PassAllTokensOn(); return Task.CompletedTask; }, b => joinBuildAction(b) @@ -31,7 +31,7 @@ public static IActivityBuilder AddFork(this IActivityBuilder builder, string for forkNodeName, c => { - c.PassAllOn(); + c.PassAllTokensOn(); return Task.CompletedTask; }, b => forkBuildAction(b) @@ -47,7 +47,7 @@ public static IActivityBuilder AddMerge(this IActivityBuilder builder, string me mergeNodeName, c => { - c.PassAllOn(); + c.PassAllTokensOn(); return Task.CompletedTask; }, b => mergeBuildAction(b.SetOptions(NodeOptions.None) as IMergeBuilder) @@ -63,32 +63,30 @@ public static IActivityBuilder AddControlDecision(this IActivityBuilder builder, decisionNodeName, c => { - c.PassAllOn(); + c.PassAllTokensOn(); return Task.CompletedTask; }, b => decisionBuildAction(b.SetOptions(NodeOptions.DecisionDefault) as IDecisionBuilder) ) as IActivityBuilder; public static IActivityBuilder AddControlDecision(this IActivityBuilder builder, DecisionBuildAction decisionBuildAction) - => builder.AddControlDecision(ActivityNodeInfo>.Name, decisionBuildAction); + => builder.AddControlDecision(ActivityNodeInfo.Name, decisionBuildAction); - public static IActivityBuilder AddTokenDecision(this IActivityBuilder builder, string decisionNodeName, DecisionBuildAction decisionBuildAction) - where TToken : Token, new() + public static IActivityBuilder AddDecision(this IActivityBuilder builder, string decisionNodeName, DecisionBuildAction decisionBuildAction) => (builder as BaseActivityBuilder) .AddNode( NodeType.Decision, decisionNodeName, c => { - c.PassAllOn(); + c.PassAllTokensOn(); return Task.CompletedTask; }, b => decisionBuildAction(new DecisionBuilder(b.SetOptions(NodeOptions.DecisionDefault) as NodeBuilder)) ) as IActivityBuilder; - public static IActivityBuilder AddTokenDecision(this IActivityBuilder builder, DecisionBuildAction decisionBuildAction) - where TToken : Token, new() - => builder.AddTokenDecision(ActivityNodeInfo>.Name, decisionBuildAction); + public static IActivityBuilder AddDecision(this IActivityBuilder builder, DecisionBuildAction decisionBuildAction) + => builder.AddDecision(ActivityNodeInfo>.Name, decisionBuildAction); public static IActivityBuilder AddDataStore(this IActivityBuilder builder, string dataStoreNodeName, DataStoreBuildAction decisionBuildAction) => (builder as BaseActivityBuilder) @@ -97,7 +95,7 @@ public static IActivityBuilder AddDataStore(this IActivityBuilder builder, strin dataStoreNodeName, c => { - c.PassAllOn(); + c.PassAllTokensOn(); return Task.CompletedTask; }, b => decisionBuildAction(b.SetOptions(NodeOptions.DataStoreDefault) as IDataStoreBuilder) diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActivityBuilder/ActivityBuilderSpecialsPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActivityBuilder/ActivityBuilderSpecialsPayloadExtensions.cs deleted file mode 100644 index b0081b83..00000000 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActivityBuilder/ActivityBuilderSpecialsPayloadExtensions.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Stateflows.Common; -using Stateflows.Activities.Registration.Interfaces; - -namespace Stateflows.Activities.Data -{ - public static class ActivityBuilderSpecialsPayloadExtensions - { - public static IActivityBuilder AddDataDecision(this IActivityBuilder builder, string decisionNodeName, DecisionBuildAction> decisionBuildAction) - => builder.AddTokenDecision>(decisionNodeName, decisionBuildAction); - } -} diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActivityBuilder/ActivityBuilderTypedExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActivityBuilder/ActivityBuilderTypedExtensions.cs index 0889a972..4000c2ed 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActivityBuilder/ActivityBuilderTypedExtensions.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActivityBuilder/ActivityBuilderTypedExtensions.cs @@ -28,10 +28,12 @@ public static IActivityBuilder AddAction(this IActivityBuilder builder, { var action = (c as BaseContext).NodeScope.GetAction(c); - InputTokensHolder.Tokens.Value = c.Input; + InputTokensHolder.Tokens.Value = ((ActionContext)c).InputTokens; OutputTokensHolder.Tokens.Value = ((ActionContext)c).OutputTokens; + ActivityNodeContextAccessor.Context.Value = c; var result = action.ExecuteAsync(); + ActivityNodeContextAccessor.Context.Value = null; return result; }), @@ -59,10 +61,12 @@ public static IActivityBuilder AddAcceptEventAction( { var action = (c as BaseContext).NodeScope.GetAcceptEventAction(c); - InputTokensHolder.Tokens.Value = c.Input; + InputTokensHolder.Tokens.Value = ((ActionContext)c).InputTokens; OutputTokensHolder.Tokens.Value = ((ActionContext)c).OutputTokens; + ActivityNodeContextAccessor.Context.Value = c; var result = action.ExecuteAsync(); + ActivityNodeContextAccessor.Context.Value = null; return result; }), @@ -89,10 +93,14 @@ private static async Task GetSendEventAction(context); - InputTokensHolder.Tokens.Value = context.Input; + InputTokensHolder.Tokens.Value = ((ActionContext)context).InputTokens; OutputTokensHolder.Tokens.Value = ((ActionContext)context).OutputTokens; - return await callback(action); + ActivityNodeContextAccessor.Context.Value = context; + var result = await callback(action); + ActivityNodeContextAccessor.Context.Value = null; + + return result; } public static IActivityBuilder AddSendEventAction(this IActivityBuilder builder, SendEventActionBuildAction buildAction = null) @@ -138,12 +146,10 @@ public static IActivityBuilder AddStructuredActivity(this I #region AddParallelActivity public static IActivityBuilder AddParallelActivity(this IActivityBuilder builder, ParallelActivityBuildAction buildAction = null) - where TParallelizationToken : Token, new() where TStructuredActivity : ParallelActivityNode => AddParallelActivity(builder, ActivityNodeInfo.Name, buildAction); public static IActivityBuilder AddParallelActivity(this IActivityBuilder builder, string structuredActivityName, ParallelActivityBuildAction buildAction = null) - where TParallelizationToken : Token, new() where TStructuredActivity : ParallelActivityNode { (builder as IInternal).Services.RegisterStructuredActivity(); @@ -163,12 +169,10 @@ public static IActivityBuilder AddParallelActivity(this IActivityBuilder builder, IterativeActivityBuildAction buildAction = null, int chunkSize = 1) - where TIterationToken : Token, new() where TStructuredActivity : IterativeActivityNode => AddIterativeActivity(builder, ActivityNodeInfo.Name, buildAction, chunkSize); public static IActivityBuilder AddIterativeActivity(this IActivityBuilder builder, string structuredActivityName, IterativeActivityBuildAction buildAction = null, int chunkSize = 1) - where TIterationToken : Token, new() where TStructuredActivity : IterativeActivityNode { (builder as IInternal).Services.RegisterStructuredActivity(); diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActivityBuilder/ActivityBuilderTypedPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActivityBuilder/ActivityBuilderTypedPayloadExtensions.cs index f9ed6c83..04c109c4 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActivityBuilder/ActivityBuilderTypedPayloadExtensions.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ActivityBuilder/ActivityBuilderTypedPayloadExtensions.cs @@ -24,25 +24,5 @@ public static IActivityBuilder AddSendEventAction> => builder.AddSendEventAction, TSendEventAction>(actionNodeName, buildAction); #endregion - - #region AddParallelActivity - public static IActivityBuilder AddParallelActivity(this IActivityBuilder builder, ParallelActivityBuildAction buildAction = null) - where TStructuredActivity : ParallelActivityNode> - => builder.AddParallelActivity(ActivityNodeInfo.Name, buildAction); - - public static IActivityBuilder AddParallelActivity(this IActivityBuilder builder, string structuredActivityName, ParallelActivityBuildAction buildAction = null) - where TStructuredActivity : ParallelActivityNode> - => builder.AddParallelActivity, TStructuredActivity>(structuredActivityName, buildAction); - #endregion - - #region AddIterativeActivity - public static IActivityBuilder AddIterativeActivity(this IActivityBuilder builder, IterativeActivityBuildAction buildAction = null) - where TStructuredActivity : IterativeActivityNode> - => builder.AddIterativeActivity(ActivityNodeInfo.Name, buildAction); - - public static IActivityBuilder AddIterativeActivity(this IActivityBuilder builder, string structuredActivityName, IterativeActivityBuildAction buildAction = null) - where TStructuredActivity : IterativeActivityNode> - => builder.AddIterativeActivity, TStructuredActivity>(structuredActivityName, buildAction); - #endregion } } diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DataStoreBuilder/Flows/DataStoreBuilderFlowsPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DataStoreBuilder/Flows/DataStoreBuilderFlowsPayloadExtensions.cs deleted file mode 100644 index 1366ed10..00000000 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DataStoreBuilder/Flows/DataStoreBuilderFlowsPayloadExtensions.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Stateflows.Common; -using Stateflows.Activities.Registration.Interfaces; - -namespace Stateflows.Activities.Data -{ - public static class DataStoreBuilderFlowsPayloadExtensions - { - public static void AddDataFlow(this IDataStoreBuilder builder, string targetNodeName, ObjectFlowBuildAction> buildAction = null) - => builder.AddFlow>(targetNodeName, buildAction); - } -} diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DataStoreBuilder/Flows/DataStoreBuilderFlowsTypedExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DataStoreBuilder/Flows/DataStoreBuilderFlowsTypedExtensions.cs index 6aaca6b1..cc070777 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DataStoreBuilder/Flows/DataStoreBuilderFlowsTypedExtensions.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DataStoreBuilder/Flows/DataStoreBuilderFlowsTypedExtensions.cs @@ -7,42 +7,35 @@ namespace Stateflows.Activities.Typed public static class DataStoreBuilderFlowsTypedExtensions { public static void AddFlow(this IDataStoreBuilder builder, ObjectFlowBuildAction buildAction = null) - where TToken : Token, new() where TTargetNode : ActivityNode => builder.AddFlow(ActivityNodeInfo.Name, buildAction); - public static void AddFlow(this IDataStoreBuilder builder, string targetNodeName) - where TToken : Token, new() - where TObjectFlow : Flow + public static void AddFlow(this IDataStoreBuilder builder, string targetNodeName) + where TFlow : Flow { - (builder as IInternal).Services.RegisterObjectFlow(); + (builder as IInternal).Services.RegisterObjectFlow(); builder.AddFlow( targetNodeName, - b => b.AddObjectFlowEvents() + b => b.AddObjectFlowEvents() ); } - public static void AddFlow(this IDataStoreBuilder builder) - where TToken : Token, new() - where TObjectFlow : Flow + public static void AddFlow(this IDataStoreBuilder builder) + where TFlow : Flow where TTargetNode : ActivityNode - => builder.AddFlow(ActivityNodeInfo.Name); + => builder.AddFlow(ActivityNodeInfo.Name); public static void AddFlow(this IDataStoreBuilder builder, string targetNodeName) - where TToken : Token, new() - where TTransformedToken : Token, new() where TObjectTransformationFlow : TransformationFlow { - (builder as IInternal).Services.RegisterObjectTransformationFlow(); + (builder as IInternal).Services.RegisterTransformationFlow(); builder.AddFlow( targetNodeName, - b => b.AddObjectTransformationFlowEvents() + b => b.AddTransformationFlowEvents() ); } public static void AddFlow(this IDataStoreBuilder builder) - where TToken : Token, new() - where TTransformedToken : Token, new() where TObjectTransformationFlow : TransformationFlow where TTargetNode : ActivityNode => builder.AddFlow(ActivityNodeInfo.Name); diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DataStoreBuilder/Flows/DataStoreBuilderFlowsTypedPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DataStoreBuilder/Flows/DataStoreBuilderFlowsTypedPayloadExtensions.cs deleted file mode 100644 index a94434e0..00000000 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DataStoreBuilder/Flows/DataStoreBuilderFlowsTypedPayloadExtensions.cs +++ /dev/null @@ -1,43 +0,0 @@ -using Stateflows.Common; -using Stateflows.Activities.Extensions; -using Stateflows.Activities.Registration.Interfaces; - -namespace Stateflows.Activities.Typed.Data -{ - public static class DataStoreBuilderFlowsTypedPayloadExtensions - { - public static void AddDataFlow(this IDataStoreBuilder builder, ObjectFlowBuildAction> buildAction = null) - where TTargetNode : ActivityNode - => builder.AddFlow>(ActivityNodeInfo.Name, buildAction); - - public static void AddDataFlow(this IDataStoreBuilder builder, string targetNodeName) - where TObjectFlow : Flow> - { - (builder as IInternal).Services.RegisterObjectFlow>(); - builder.AddFlow>( - targetNodeName, - b => b.AddObjectFlowEvents>() - ); - } - - public static void AddDataFlow(this IDataStoreBuilder builder) - where TObjectFlow : Flow> - where TTargetNode : ActivityNode - => builder.AddFlow, TObjectFlow>(ActivityNodeInfo.Name); - - public static void AddDataFlow(this IDataStoreBuilder builder, string targetNodeName) - where TObjectTransformationFlow : TransformationFlow, Token> - { - (builder as IInternal).Services.RegisterObjectTransformationFlow, Token>(); - builder.AddFlow>( - targetNodeName, - b => b.AddObjectTransformationFlowEvents, Token>() - ); - } - - public static void AddDataFlow(this IDataStoreBuilder builder) - where TObjectTransformationFlow : TransformationFlow, Token> - where TTargetNode : ActivityNode - => builder.AddFlow, Token, TObjectTransformationFlow>(ActivityNodeInfo.Name); - } -} diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DecisionBuilder/ElseFlows/DecisionBuilderElseObjectFlowsPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DecisionBuilder/ElseFlows/DecisionBuilderElseObjectFlowsPayloadExtensions.cs deleted file mode 100644 index ab0a960f..00000000 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DecisionBuilder/ElseFlows/DecisionBuilderElseObjectFlowsPayloadExtensions.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Stateflows.Common; -using Stateflows.Activities.Registration.Interfaces; - -namespace Stateflows.Activities -{ - public static class DecisionBuilderElseObjectFlowsPayloadExtensions - { - //public static IDecisionBuilder> AddElseFlow(this IDecisionBuilder> builder, string targetNodeName, ObjectFlowBuildAction> buildAction = null) - // => builder.AddElseFlow(targetNodeName, b => buildAction?.Invoke(b as IObjectFlowBuilder>)); - } -} diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DecisionBuilder/ElseFlows/DecisionBuilderElseObjectFlowsTypedExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DecisionBuilder/ElseFlows/DecisionBuilderElseObjectFlowsTypedExtensions.cs index feb74916..fdbeef28 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DecisionBuilder/ElseFlows/DecisionBuilderElseObjectFlowsTypedExtensions.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DecisionBuilder/ElseFlows/DecisionBuilderElseObjectFlowsTypedExtensions.cs @@ -1,52 +1,44 @@ -using Stateflows.Common; -using Stateflows.Activities.Extensions; +using Stateflows.Activities.Extensions; using Stateflows.Activities.Registration.Interfaces; namespace Stateflows.Activities.Typed { public static class DecisionBuilderElseObjectFlowsTypedExtensions { - public static IDecisionBuilder AddElseFlow(this IDecisionBuilder builder, ObjectFlowBuildAction buildAction = null) - where TToken : Token, new() - where TTargetNode : ActivityNode - => builder.AddElseFlow(ActivityNodeInfo.Name, b => buildAction?.Invoke(b as IObjectFlowBuilder)); + // public static IDecisionBuilder AddElseFlow(this IDecisionBuilder builder, ObjectFlowBuildAction buildAction = null) + // where TTargetNode : ActivityNode + // => builder.AddElseFlow(ActivityNodeInfo.Name, b => buildAction?.Invoke(b as IObjectFlowBuilder)); - public static IDecisionBuilder AddElseFlow(this IDecisionBuilder builder, string targetNodeName) - where TToken : Token, new() - where TObjectFlow : Flow - { - (builder as IInternal).Services.RegisterObjectFlow(); + // public static IDecisionBuilder AddElseFlow(this IDecisionBuilder builder, string targetNodeName) + // where TFlow : Flow + // { + // (builder as IInternal).Services.RegisterObjectFlow(); - return builder.AddElseFlow( - targetNodeName, - b => (b as IObjectFlowBuilder).AddObjectFlowEvents() - ); - } + // return builder.AddElseFlow( + // targetNodeName, + // b => (b as IObjectFlowBuilder).AddObjectFlowEvents() + // ); + // } - public static IDecisionBuilder AddElseFlow(this IDecisionBuilder builder) - where TToken : Token, new() - where TObjectFlow : Flow - where TTargetNode : ActivityNode - => builder.AddElseFlow(ActivityNodeInfo.Name); + // public static IDecisionBuilder AddElseFlow(this IDecisionBuilder builder) + // where TFlow : Flow + // where TTargetNode : ActivityNode + // => builder.AddElseFlow(ActivityNodeInfo.Name); - public static IDecisionBuilder AddElseFlow(this IDecisionBuilder builder, string targetNodeName) - where TToken : Token, new() - where TTransformedToken : Token, new() - where TObjectTransformationFlow : TransformationFlow - { - (builder as IInternal).Services.RegisterObjectTransformationFlow(); + // public static IDecisionBuilder AddElseFlow(this IDecisionBuilder builder, string targetNodeName) + // where TObjectTransformationFlow : TransformationFlow + // { + // (builder as IInternal).Services.RegisterObjectTransformationFlow(); - return builder.AddElseFlow( - targetNodeName, - b => (b as IObjectFlowBuilder).AddObjectTransformationFlowEvents() - ); - } + // return builder.AddElseFlow( + // targetNodeName, + // b => (b as IObjectFlowBuilder).AddObjectTransformationFlowEvents() + // ); + // } - public static IDecisionBuilder AddElseFlow(this IDecisionBuilder builder) - where TToken : Token, new() - where TTransformedToken : Token, new() - where TObjectTransformationFlow : TransformationFlow - where TTargetNode : ActivityNode - => builder.AddElseFlow(ActivityNodeInfo.Name); + // public static IDecisionBuilder AddElseFlow(this IDecisionBuilder builder) + // where TObjectTransformationFlow : TransformationFlow + // where TTargetNode : ActivityNode + // => builder.AddElseFlow(ActivityNodeInfo.Name); } } diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DecisionBuilder/ElseFlows/DecisionBuilderElseObjectFlowsTypedPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DecisionBuilder/ElseFlows/DecisionBuilderElseObjectFlowsTypedPayloadExtensions.cs deleted file mode 100644 index 0518a17c..00000000 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DecisionBuilder/ElseFlows/DecisionBuilderElseObjectFlowsTypedPayloadExtensions.cs +++ /dev/null @@ -1,45 +0,0 @@ -using Stateflows.Common; -using Stateflows.Activities.Extensions; -using Stateflows.Activities.Registration.Interfaces; - -namespace Stateflows.Activities.Typed.Data -{ - public static class DecisionBuilderElseObjectFlowsTypedPayloadExtensions - { - public static IDecisionBuilder> AddElseFlow(this IDecisionBuilder> builder, ObjectFlowBuildAction> buildAction = null) - where TTargetNode : ActivityNode - => builder.AddElseFlow(ActivityNodeInfo.Name, b => buildAction?.Invoke(b as IObjectFlowBuilder>)); - - public static IDecisionBuilder> AddElseFlow(this IDecisionBuilder> builder, string targetNodeName) - where TObjectFlow : Flow> - { - (builder as IInternal).Services.RegisterObjectFlow>(); - - return builder.AddElseFlow( - targetNodeName, - b => (b as IObjectFlowBuilder>).AddObjectFlowEvents>() - ); - } - - public static IDecisionBuilder> AddElseFlow(this IDecisionBuilder> builder) - where TObjectFlow : Flow> - where TTargetNode : ActivityNode - => builder.AddElseFlow, TObjectFlow>(ActivityNodeInfo.Name); - - public static IDecisionBuilder> AddElseFlow(this IDecisionBuilder> builder, string targetNodeName) - where TObjectTransformationFlow : TransformationFlow, Token> - { - (builder as IInternal).Services.RegisterObjectTransformationFlow, Token>(); - - return builder.AddElseFlow( - targetNodeName, - b => (b as IObjectFlowBuilder>).AddObjectTransformationFlowEvents, Token>() - ); - } - - public static IDecisionBuilder> AddElseFlow(this IDecisionBuilder> builder) - where TObjectTransformationFlow : TransformationFlow, Token> - where TTargetNode : ActivityNode - => builder.AddElseFlow, Token, TObjectTransformationFlow>(ActivityNodeInfo.Name); - } -} diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DecisionBuilder/Flows/DecisionBuilderObjectFlowsPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DecisionBuilder/Flows/DecisionBuilderObjectFlowsPayloadExtensions.cs deleted file mode 100644 index fad99dd7..00000000 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DecisionBuilder/Flows/DecisionBuilderObjectFlowsPayloadExtensions.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Stateflows.Common; -using Stateflows.Activities.Registration.Interfaces; - -namespace Stateflows.Activities.Data -{ - public static class DecisionBuilderObjectFlowsPayloadExtensions - { - public static IDecisionBuilder> AddFlow(this IDecisionBuilder> builder, string targetNodeName, ObjectFlowBuildAction> buildAction = null) - => builder.AddFlow(targetNodeName, buildAction); - } -} diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DecisionBuilder/Flows/DecisionBuilderObjectFlowsTypedExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DecisionBuilder/Flows/DecisionBuilderObjectFlowsTypedExtensions.cs index f481e2fc..c1910902 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DecisionBuilder/Flows/DecisionBuilderObjectFlowsTypedExtensions.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DecisionBuilder/Flows/DecisionBuilderObjectFlowsTypedExtensions.cs @@ -1,52 +1,44 @@ -using Stateflows.Common; -using Stateflows.Activities.Extensions; +using Stateflows.Activities.Extensions; using Stateflows.Activities.Registration.Interfaces; namespace Stateflows.Activities.Typed { public static class DecisionBuilderObjectFlowsTypedExtensions { - public static IDecisionBuilder AddFlow(this IDecisionBuilder builder, ObjectFlowBuildAction buildAction = null) - where TToken : Token, new() - where TTargetNode : ActivityNode - => builder.AddFlow(ActivityNodeInfo.Name, buildAction); + //public static IDecisionBuilder AddFlow(this IDecisionBuilder builder, ObjectFlowBuildAction buildAction = null) + // where TTargetNode : ActivityNode + // => builder.AddFlow(ActivityNodeInfo.Name, buildAction); - public static IDecisionBuilder AddFlow(this IDecisionBuilder builder, string targetNodeName) - where TToken : Token, new() - where TObjectFlow : Flow - { - (builder as IInternal).Services.RegisterObjectFlow(); + //public static IDecisionBuilder AddFlow(this IDecisionBuilder builder, string targetNodeName) + // where TFlow : Flow + //{ + // (builder as IInternal).Services.RegisterObjectFlow(); - return builder.AddFlow( - targetNodeName, - b => b.AddObjectFlowEvents() - ); - } + // return builder.AddFlow( + // targetNodeName, + // b => b.AddObjectFlowEvents() + // ); + //} - public static IDecisionBuilder AddFlow(this IDecisionBuilder builder) - where TToken : Token, new() - where TObjectFlow : Flow - where TTargetNode : ActivityNode - => builder.AddFlow(ActivityNodeInfo.Name); + //public static IDecisionBuilder AddFlow(this IDecisionBuilder builder) + // where TFlow : Flow + // where TTargetNode : ActivityNode + // => builder.AddFlow(ActivityNodeInfo.Name); - public static IDecisionBuilder AddFlow(this IDecisionBuilder builder, string targetNodeName) - where TToken : Token, new() - where TTransformedToken : Token, new() - where TObjectTransformationFlow : TransformationFlow - { - (builder as IInternal).Services.RegisterObjectTransformationFlow(); + //public static IDecisionBuilder AddFlow(this IDecisionBuilder builder, string targetNodeName) + // where TObjectTransformationFlow : TransformationFlow + //{ + // (builder as IInternal).Services.RegisterObjectTransformationFlow(); - return builder.AddFlow( - targetNodeName, - b => b.AddObjectTransformationFlowEvents() - ); - } + // return builder.AddFlow( + // targetNodeName, + // b => b.AddObjectTransformationFlowEvents() + // ); + //} - public static IDecisionBuilder AddFlow(this IDecisionBuilder builder) - where TToken : Token, new() - where TTransformedToken : Token, new() - where TObjectTransformationFlow : TransformationFlow - where TTargetNode : ActivityNode - => builder.AddFlow(ActivityNodeInfo.Name); + //public static IDecisionBuilder AddFlow(this IDecisionBuilder builder) + // where TObjectTransformationFlow : TransformationFlow + // where TTargetNode : ActivityNode + // => builder.AddFlow(ActivityNodeInfo.Name); } } diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DecisionBuilder/Flows/DecisionBuilderObjectFlowsTypedPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DecisionBuilder/Flows/DecisionBuilderObjectFlowsTypedPayloadExtensions.cs deleted file mode 100644 index 5cb6f283..00000000 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/DecisionBuilder/Flows/DecisionBuilderObjectFlowsTypedPayloadExtensions.cs +++ /dev/null @@ -1,45 +0,0 @@ -using Stateflows.Common; -using Stateflows.Activities.Extensions; -using Stateflows.Activities.Registration.Interfaces; - -namespace Stateflows.Activities.Typed.Data -{ - public static class DecisionBuilderObjectFlowsTypedPayloadExtensions - { - public static IDecisionBuilder> AddFlow(this IDecisionBuilder> builder, ObjectFlowBuildAction> buildAction = null) - where TTargetNode : ActivityNode - => builder.AddFlow(ActivityNodeInfo.Name, buildAction); - - public static IDecisionBuilder> AddFlow(this IDecisionBuilder> builder, string targetNodeName) - where TObjectFlow : Flow> - { - (builder as IInternal).Services.RegisterObjectFlow>(); - - return builder.AddFlow( - targetNodeName, - b => b.AddObjectFlowEvents>() - ); - } - - public static IDecisionBuilder> AddFlow(this IDecisionBuilder> builder) - where TObjectFlow : Flow> - where TTargetNode : ActivityNode - => builder.AddFlow, TObjectFlow>(ActivityNodeInfo.Name); - - public static IDecisionBuilder> AddFlow(this IDecisionBuilder> builder, string targetNodeName) - where TObjectTransformationFlow : TransformationFlow, Token> - { - (builder as IInternal).Services.RegisterObjectTransformationFlow, Token>(); - - return builder.AddFlow( - targetNodeName, - b => b.AddObjectTransformationFlowEvents, Token>() - ); - } - - public static IDecisionBuilder> AddFlow(this IDecisionBuilder> builder) - where TObjectTransformationFlow : TransformationFlow, Token> - where TTargetNode : ActivityNode - => builder.AddFlow, Token, TObjectTransformationFlow>(ActivityNodeInfo.Name); - } -} diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/InputBuilder/Flows/InputBuilderControlFlowsTypedExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/InputBuilder/Flows/InputBuilderControlFlowsTypedExtensions.cs index ecec98df..8fa0374b 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/InputBuilder/Flows/InputBuilderControlFlowsTypedExtensions.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/InputBuilder/Flows/InputBuilderControlFlowsTypedExtensions.cs @@ -1,5 +1,4 @@ -using Stateflows.Activities.Extensions; -using Stateflows.Activities.Registration.Interfaces; +using Stateflows.Activities.Registration.Interfaces; namespace Stateflows.Activities.Typed { diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/InputBuilder/Flows/InputBuilderFlowsPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/InputBuilder/Flows/InputBuilderFlowsPayloadExtensions.cs deleted file mode 100644 index 27be2063..00000000 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/InputBuilder/Flows/InputBuilderFlowsPayloadExtensions.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Stateflows.Common; -using Stateflows.Activities.Registration.Interfaces; - -namespace Stateflows.Activities.Data -{ - public static class InputBuilderFlowsPayloadExtensions - { - public static IInputBuilder AddDataFlow(this IInputBuilder builder, string targetNodeName, ObjectFlowBuildAction> buildAction = null) - => builder.AddFlow>(targetNodeName, buildAction); - } -} diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/InputBuilder/Flows/InputBuilderFlowsTypedExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/InputBuilder/Flows/InputBuilderFlowsTypedExtensions.cs index 0409cee9..7cfb46e4 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/InputBuilder/Flows/InputBuilderFlowsTypedExtensions.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/InputBuilder/Flows/InputBuilderFlowsTypedExtensions.cs @@ -1,35 +1,27 @@ -using Stateflows.Common; -using Stateflows.Activities.Registration.Interfaces; +using Stateflows.Activities.Registration.Interfaces; namespace Stateflows.Activities.Typed { public static class InputBuilderFlowsTypedExtensions { public static IInputBuilder AddFlow(this IInputBuilder builder, ObjectFlowBuildAction buildAction = null) - where TToken : Token, new() where TTargetNode : ActivityNode => builder.AddFlow(ActivityNodeInfo.Name, buildAction); - public static IInputBuilder AddFlow(this IInputBuilder builder, string targetNodeName) - where TToken : Token, new() - where TObjectFlow : Flow - => (builder as IActionBuilder).AddFlow(targetNodeName) as IInputBuilder; + public static IInputBuilder AddFlow(this IInputBuilder builder, string targetNodeName) + where TFlow : Flow + => (builder as IActionBuilder).AddFlow(targetNodeName) as IInputBuilder; public static IInputBuilder AddFlow(this IInputBuilder builder) - where TToken : Token, new() where TFlow : Flow where TTargetNode : ActivityNode => builder.AddFlow(ActivityNodeInfo.Name); public static IInputBuilder AddFlow(this IInputBuilder builder, string targetNodeName) - where TToken : Token, new() - where TTransformedToken : Token, new() where TFlow : TransformationFlow => (builder as IActionBuilder).AddFlow(targetNodeName) as IInputBuilder; public static IInputBuilder AddFlow(this IInputBuilder builder) - where TToken : Token, new() - where TTransformedToken : Token, new() where TFlow : TransformationFlow where TTargetNode : ActivityNode => builder.AddFlow(ActivityNodeInfo.Name); diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/InputBuilder/Flows/InputBuilderFlowsTypedPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/InputBuilder/Flows/InputBuilderFlowsTypedPayloadExtensions.cs deleted file mode 100644 index 7446a1b2..00000000 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/InputBuilder/Flows/InputBuilderFlowsTypedPayloadExtensions.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Stateflows.Common; -using Stateflows.Activities.Registration.Interfaces; - -namespace Stateflows.Activities.Typed.Data -{ - public static class InputBuilderFlowsTypedPayloadExtensions - { - public static IInputBuilder AddDataFlow(this IInputBuilder builder, ObjectFlowBuildAction> buildAction = null) - where TTargetNode : ActivityNode - => builder.AddFlow>(ActivityNodeInfo.Name, buildAction); - - public static IInputBuilder AddDataFlow(this IInputBuilder builder, string targetNodeName) - where TObjectFlow : Flow> - => (builder as IActionBuilder).AddFlow, TObjectFlow>(targetNodeName) as IInputBuilder; - - public static IInputBuilder AddDataFlow(this IInputBuilder builder) - where TFlow : Flow> - where TTargetNode : ActivityNode - => builder.AddFlow, TFlow>(ActivityNodeInfo.Name); - - public static IInputBuilder AddDataFlow(this IInputBuilder builder, string targetNodeName) - where TFlow : TransformationFlow, Token> - => (builder as IActionBuilder).AddFlow, Token, TFlow>(targetNodeName) as IInputBuilder; - - public static IInputBuilder AddDataFlow(this IInputBuilder builder) - where TFlow : TransformationFlow, Token> - where TTargetNode : ActivityNode - => builder.AddFlow, Token, TFlow>(ActivityNodeInfo.Name); - } -} diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/JoinBuilder/Flows/JoinBuilderFlowsPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/JoinBuilder/Flows/JoinBuilderFlowsPayloadExtensions.cs deleted file mode 100644 index 757c2aed..00000000 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/JoinBuilder/Flows/JoinBuilderFlowsPayloadExtensions.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Stateflows.Common; -using Stateflows.Activities.Registration.Interfaces; - -namespace Stateflows.Activities.Data -{ - public static class JoinBuilderFlowsPayloadExtensions - { - public static void AddDataFlow(this IJoinBuilder builder, string targetNodeName, ObjectFlowBuildAction> buildAction = null) - => builder.AddFlow>(targetNodeName, buildAction); - } -} diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/JoinBuilder/Flows/JoinBuilderFlowsTypedExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/JoinBuilder/Flows/JoinBuilderFlowsTypedExtensions.cs index 65d9481f..97c80334 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/JoinBuilder/Flows/JoinBuilderFlowsTypedExtensions.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/JoinBuilder/Flows/JoinBuilderFlowsTypedExtensions.cs @@ -1,5 +1,4 @@ -using Stateflows.Common; -using Stateflows.Activities.Extensions; +using Stateflows.Activities.Extensions; using Stateflows.Activities.Registration.Interfaces; namespace Stateflows.Activities.Typed @@ -7,42 +6,35 @@ namespace Stateflows.Activities.Typed public static class JoinBuilderFlowsTypedExtensions { public static void AddFlow(this IJoinBuilder builder, ObjectFlowBuildAction buildAction = null) - where TToken : Token, new() where TTargetNode : ActivityNode => builder.AddFlow(ActivityNodeInfo.Name, buildAction); - public static void AddFlow(this IJoinBuilder builder, string targetNodeName) - where TToken : Token, new() - where TObjectFlow : Flow + public static void AddFlow(this IJoinBuilder builder, string targetNodeName) + where TFlow : Flow { - (builder as IInternal).Services.RegisterObjectFlow(); + (builder as IInternal).Services.RegisterObjectFlow(); builder.AddFlow( targetNodeName, - b => b.AddObjectFlowEvents() + b => b.AddObjectFlowEvents() ); } - public static void AddFlow(this IJoinBuilder builder) - where TToken : Token, new() - where TObjectFlow : Flow + public static void AddFlow(this IJoinBuilder builder) + where TFlow : Flow where TTargetNode : ActivityNode - => builder.AddFlow(ActivityNodeInfo.Name); + => builder.AddFlow(ActivityNodeInfo.Name); public static void AddFlow(this IJoinBuilder builder, string targetNodeName) - where TToken : Token, new() - where TTransformedToken : Token, new() where TObjectTransformationFlow : TransformationFlow { - (builder as IInternal).Services.RegisterObjectTransformationFlow(); + (builder as IInternal).Services.RegisterTransformationFlow(); builder.AddFlow( targetNodeName, - b => b.AddObjectTransformationFlowEvents() + b => b.AddTransformationFlowEvents() ); } public static void AddFlow(this IJoinBuilder builder) - where TToken : Token, new() - where TTransformedToken : Token, new() where TObjectTransformationFlow : TransformationFlow where TTargetNode : ActivityNode => builder.AddFlow(ActivityNodeInfo.Name); diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/JoinBuilder/Flows/JoinBuilderFlowsTypedPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/JoinBuilder/Flows/JoinBuilderFlowsTypedPayloadExtensions.cs deleted file mode 100644 index 56fad1b9..00000000 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/JoinBuilder/Flows/JoinBuilderFlowsTypedPayloadExtensions.cs +++ /dev/null @@ -1,43 +0,0 @@ -using Stateflows.Common; -using Stateflows.Activities.Extensions; -using Stateflows.Activities.Registration.Interfaces; - -namespace Stateflows.Activities.Typed.Data -{ - public static class JoinBuilderFlowsTypedPayloadExtensions - { - public static void AddDataFlow(this IJoinBuilder builder, ObjectFlowBuildAction> buildAction = null) - where TTargetNode : ActivityNode - => builder.AddFlow>(ActivityNodeInfo.Name, buildAction); - - public static void AddDataFlow(this IJoinBuilder builder, string targetNodeName) - where TObjectFlow : Flow> - { - (builder as IInternal).Services.RegisterObjectFlow>(); - builder.AddFlow>( - targetNodeName, - b => b.AddObjectFlowEvents>() - ); - } - - public static void AddDataFlow(this IJoinBuilder builder) - where TObjectFlow : Flow> - where TTargetNode : ActivityNode - => builder.AddFlow, TObjectFlow>(ActivityNodeInfo.Name); - - public static void AddDataFlow(this IJoinBuilder builder, string targetNodeName) - where TObjectTransformationFlow : TransformationFlow, Token> - { - (builder as IInternal).Services.RegisterObjectTransformationFlow, Token>(); - builder.AddFlow>( - targetNodeName, - b => b.AddObjectTransformationFlowEvents, Token>() - ); - } - - public static void AddDataFlow(this IJoinBuilder builder) - where TObjectTransformationFlow : TransformationFlow, Token> - where TTargetNode : ActivityNode - => builder.AddFlow, Token, TObjectTransformationFlow>(ActivityNodeInfo.Name); - } -} diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/MergeBuilder/Flows/MergeBuilderObjectFlowsPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/MergeBuilder/Flows/MergeBuilderObjectFlowsPayloadExtensions.cs deleted file mode 100644 index d78774b2..00000000 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/MergeBuilder/Flows/MergeBuilderObjectFlowsPayloadExtensions.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Stateflows.Common; -using Stateflows.Activities.Extensions; -using Stateflows.Activities.Registration.Interfaces; - -namespace Stateflows.Activities.Data -{ - public static class MergeBuilderObjectFlowsPayloadExtensions - { - public static void AddDataFlow(this IMergeBuilder builder, string targetNodeName, ObjectFlowBuildAction> buildAction = null) - => builder.AddFlow>(targetNodeName, buildAction); - } -} diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/MergeBuilder/Flows/MergeBuilderObjectFlowsTypedExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/MergeBuilder/Flows/MergeBuilderObjectFlowsTypedExtensions.cs index 5ecff06c..6b0988b7 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/MergeBuilder/Flows/MergeBuilderObjectFlowsTypedExtensions.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/MergeBuilder/Flows/MergeBuilderObjectFlowsTypedExtensions.cs @@ -7,42 +7,35 @@ namespace Stateflows.Activities.Typed public static class MergeBuilderObjectFlowsTypedExtensions { public static void AddFlow(this IMergeBuilder builder, ObjectFlowBuildAction buildAction = null) - where TToken : Token, new() where TTargetNode : ActivityNode => builder.AddFlow(ActivityNodeInfo.Name, buildAction); - public static void AddFlow(this IMergeBuilder builder, string targetNodeName) - where TToken : Token, new() - where TObjectFlow : Flow + public static void AddFlow(this IMergeBuilder builder, string targetNodeName) + where TFlow : Flow { - (builder as IInternal).Services.RegisterObjectFlow(); + (builder as IInternal).Services.RegisterObjectFlow(); builder.AddFlow( targetNodeName, - b => b.AddObjectFlowEvents() + b => b.AddObjectFlowEvents() ); } - public static void AddFlow(this IMergeBuilder builder) - where TToken : Token, new() - where TObjectFlow : Flow + public static void AddFlow(this IMergeBuilder builder) + where TFlow : Flow where TTargetNode : ActivityNode - => builder.AddFlow(ActivityNodeInfo.Name); + => builder.AddFlow(ActivityNodeInfo.Name); public static void AddFlow(this IMergeBuilder builder, string targetNodeName) - where TToken : Token, new() - where TTransformedToken : Token, new() where TObjectTransformationFlow : TransformationFlow { - (builder as IInternal).Services.RegisterObjectTransformationFlow(); + (builder as IInternal).Services.RegisterTransformationFlow(); builder.AddFlow( targetNodeName, - b => b.AddObjectTransformationFlowEvents() + b => b.AddTransformationFlowEvents() ); } public static void AddFlow(this IMergeBuilder builder) - where TToken : Token, new() - where TTransformedToken : Token, new() where TObjectTransformationFlow : TransformationFlow where TTargetNode : ActivityNode => builder.AddFlow(ActivityNodeInfo.Name); diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/MergeBuilder/Flows/MergeBuilderObjectFlowsTypedPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/MergeBuilder/Flows/MergeBuilderObjectFlowsTypedPayloadExtensions.cs deleted file mode 100644 index 20b8e619..00000000 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/MergeBuilder/Flows/MergeBuilderObjectFlowsTypedPayloadExtensions.cs +++ /dev/null @@ -1,43 +0,0 @@ -using Stateflows.Common; -using Stateflows.Activities.Extensions; -using Stateflows.Activities.Registration.Interfaces; - -namespace Stateflows.Activities.Typed.Data -{ - public static class MergeBuilderObjectFlowsTypedPayloadExtensions - { - public static void AddDataFlow(this IMergeBuilder builder, ObjectFlowBuildAction> buildAction = null) - where TTargetNode : ActivityNode - => builder.AddFlow>(ActivityNodeInfo.Name, buildAction); - - public static void AddDataFlow(this IMergeBuilder builder, string targetNodeName) - where TObjectFlow : Flow> - { - (builder as IInternal).Services.RegisterObjectFlow>(); - builder.AddFlow>( - targetNodeName, - b => b.AddObjectFlowEvents>() - ); - } - - public static void AddDataFlow(this IMergeBuilder builder) - where TObjectFlow : Flow> - where TTargetNode : ActivityNode - => builder.AddFlow, TObjectFlow>(ActivityNodeInfo.Name); - - public static void AddDataFlow(this IMergeBuilder builder, string targetNodeName) - where TObjectTransformationFlow : TransformationFlow, Token> - { - (builder as IInternal).Services.RegisterObjectTransformationFlow, Token>(); - builder.AddFlow>( - targetNodeName, - b => b.AddObjectTransformationFlowEvents, Token>() - ); - } - - public static void AddDataFlow(this IMergeBuilder builder) - where TObjectTransformationFlow : TransformationFlow, Token> - where TTargetNode : ActivityNode - => builder.AddFlow, Token, TObjectTransformationFlow>(ActivityNodeInfo.Name); - } -} diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/Flows/ReactiveStructuredActivityBuilderFlowsPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/Flows/ReactiveStructuredActivityBuilderFlowsPayloadExtensions.cs deleted file mode 100644 index d9774227..00000000 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/Flows/ReactiveStructuredActivityBuilderFlowsPayloadExtensions.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Stateflows.Common; -using Stateflows.Activities.Registration.Interfaces; - -namespace Stateflows.Activities.Data -{ - public static class ReactiveStructuredActivityBuilderFlowsPayloadExtensions - { - public static IReactiveStructuredActivityBuilder AddDataFlow(this IReactiveStructuredActivityBuilder builder, string targetNodeName, ObjectFlowBuildAction> buildAction = null) - => builder.AddFlow>(targetNodeName, buildAction); - } -} diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/Flows/ReactiveStructuredActivityBuilderFlowsTypedExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/Flows/ReactiveStructuredActivityBuilderFlowsTypedExtensions.cs index 4c040a80..c63e7244 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/Flows/ReactiveStructuredActivityBuilderFlowsTypedExtensions.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/Flows/ReactiveStructuredActivityBuilderFlowsTypedExtensions.cs @@ -1,35 +1,27 @@ using Stateflows.Activities.Registration.Interfaces; -using Stateflows.Common; namespace Stateflows.Activities.Typed { public static class ReactiveStructuredActivityBuilderFlowsTypedExtensions { public static IReactiveStructuredActivityBuilder AddFlow(this IReactiveStructuredActivityBuilder builder, ObjectFlowBuildAction buildAction = null) - where TToken : Token, new() where TTargetNode : ActivityNode => builder.AddFlow(ActivityNodeInfo.Name, buildAction); - public static IReactiveStructuredActivityBuilder AddFlow(this IReactiveStructuredActivityBuilder builder, string targetNodeName) - where TToken : Token, new() - where TObjectFlow : Flow - => (builder as IActionBuilder).AddFlow(targetNodeName) as IReactiveStructuredActivityBuilder; + public static IReactiveStructuredActivityBuilder AddFlow(this IReactiveStructuredActivityBuilder builder, string targetNodeName) + where TFlow : Flow + => (builder as IActionBuilder).AddFlow(targetNodeName) as IReactiveStructuredActivityBuilder; public static IReactiveStructuredActivityBuilder AddFlow(this IReactiveStructuredActivityBuilder builder) - where TToken : Token, new() where TFlow : Flow where TTargetNode : ActivityNode => builder.AddFlow(ActivityNodeInfo.Name); public static IReactiveStructuredActivityBuilder AddFlow(this IReactiveStructuredActivityBuilder builder, string targetNodeName) - where TToken : Token, new() - where TTransformedToken : Token, new() where TFlow : TransformationFlow => (builder as IActionBuilder).AddFlow(targetNodeName) as IReactiveStructuredActivityBuilder; public static IReactiveStructuredActivityBuilder AddFlow(this IReactiveStructuredActivityBuilder builder) - where TToken : Token, new() - where TTransformedToken : Token, new() where TFlow : TransformationFlow where TTargetNode : ActivityNode => builder.AddFlow(ActivityNodeInfo.Name); diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/Flows/ReactiveStructuredActivityBuilderFlowsTypedPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/Flows/ReactiveStructuredActivityBuilderFlowsTypedPayloadExtensions.cs deleted file mode 100644 index 2c497e00..00000000 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/Flows/ReactiveStructuredActivityBuilderFlowsTypedPayloadExtensions.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Stateflows.Common; -using Stateflows.Activities.Registration.Interfaces; - -namespace Stateflows.Activities.Typed.Data -{ - public static class ReactiveStructuredActivityBuilderFlowsTypedPayloadExtensions - { - public static IReactiveStructuredActivityBuilder AddDataFlow(this IReactiveStructuredActivityBuilder builder, ObjectFlowBuildAction> buildAction = null) - where TTargetNode : ActivityNode - => builder.AddFlow>(ActivityNodeInfo.Name, buildAction); - - public static IReactiveStructuredActivityBuilder AddDataFlow(this IReactiveStructuredActivityBuilder builder, string targetNodeName) - where TObjectFlow : Flow> - => (builder as IActionBuilder).AddFlow, TObjectFlow>(targetNodeName) as IReactiveStructuredActivityBuilder; - - public static IReactiveStructuredActivityBuilder AddDataFlow(this IReactiveStructuredActivityBuilder builder) - where TFlow : Flow> - where TTargetNode : ActivityNode - => builder.AddFlow, TFlow>(ActivityNodeInfo.Name); - - public static IReactiveStructuredActivityBuilder AddDataFlow(this IReactiveStructuredActivityBuilder builder, string targetNodeName) - where TFlow : TransformationFlow, Token> - => (builder as IActionBuilder).AddFlow, Token, TFlow>(targetNodeName) as IReactiveStructuredActivityBuilder; - - public static IReactiveStructuredActivityBuilder AddDataFlow(this IReactiveStructuredActivityBuilder builder) - where TFlow : TransformationFlow, Token> - where TTargetNode : ActivityNode - => builder.AddFlow, Token, TFlow>(ActivityNodeInfo.Name); - } -} diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/ReactiveStructuredActivityBuilderAnonymousExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/ReactiveStructuredActivityBuilderAnonymousExtensions.cs index 9cc27510..c13480f7 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/ReactiveStructuredActivityBuilderAnonymousExtensions.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/ReactiveStructuredActivityBuilderAnonymousExtensions.cs @@ -1,5 +1,4 @@ -using Stateflows.Common; -using Stateflows.Activities.Registration.Interfaces; +using Stateflows.Activities.Registration.Interfaces; namespace Stateflows.Activities.Typed { @@ -9,11 +8,9 @@ public static IReactiveStructuredActivityBuilder AddStructuredActivity(this IRea => builder.AddStructuredActivity(ActivityNodeInfo.Name, buildAction); public static IReactiveStructuredActivityBuilder AddParallelActivity(this IReactiveStructuredActivityBuilder builder, ParallelActivityBuildAction buildAction, int chunkSize = 1) - where TParallelizationToken : Token, new() => builder.AddParallelActivity(ActivityNodeInfo>.Name, buildAction, chunkSize); public static IReactiveStructuredActivityBuilder AddIterativeActivity(this IReactiveStructuredActivityBuilder builder, IterativeActivityBuildAction buildAction, int chunkSize = 1) - where TIterationToken : Token, new() => builder.AddIterativeActivity(ActivityNodeInfo>.Name, buildAction, chunkSize); } } diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/ReactiveStructuredActivityBuilderSpecialsExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/ReactiveStructuredActivityBuilderSpecialsExtensions.cs index e625bc04..98995eda 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/ReactiveStructuredActivityBuilderSpecialsExtensions.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/ReactiveStructuredActivityBuilderSpecialsExtensions.cs @@ -15,7 +15,7 @@ public static IReactiveStructuredActivityBuilder AddJoin(this IReactiveStructure joinNodeName, c => { - c.PassAllOn(); + c.PassAllTokensOn(); return Task.CompletedTask; }, b => buildAction(b) @@ -31,7 +31,7 @@ public static IReactiveStructuredActivityBuilder AddFork(this IReactiveStructure forkNodeName, c => { - c.PassAllOn(); + c.PassAllTokensOn(); return Task.CompletedTask; }, b => buildAction(b) @@ -47,7 +47,7 @@ public static IReactiveStructuredActivityBuilder AddMerge(this IReactiveStructur mergeNodeName, c => { - c.PassAllOn(); + c.PassAllTokensOn(); return Task.CompletedTask; }, b => buildAction(b.SetOptions(NodeOptions.None) as IMergeBuilder) @@ -63,32 +63,30 @@ public static IReactiveStructuredActivityBuilder AddControlDecision(this IReacti decisionNodeName, c => { - c.PassAllOn(); + c.PassAllTokensOn(); return Task.CompletedTask; }, b => buildAction(b.SetOptions(NodeOptions.DecisionDefault) as IDecisionBuilder) ) as IReactiveStructuredActivityBuilder; public static IReactiveStructuredActivityBuilder AddControlDecision(this IReactiveStructuredActivityBuilder builder, DecisionBuildAction decisionBuildAction) - => builder.AddControlDecision(ActivityNodeInfo>.Name, decisionBuildAction); + => builder.AddControlDecision(ActivityNodeInfo>.Name, decisionBuildAction); - public static IReactiveStructuredActivityBuilder AddTokenDecision(this IReactiveStructuredActivityBuilder builder, string decisionNodeName, DecisionBuildAction buildAction) - where TToken : Token, new() + public static IReactiveStructuredActivityBuilder AddDecision(this IReactiveStructuredActivityBuilder builder, string decisionNodeName, DecisionBuildAction buildAction) => (builder as BaseActivityBuilder) .AddNode( NodeType.Decision, decisionNodeName, c => { - c.PassAllOn(); + c.PassAllTokensOn(); return Task.CompletedTask; }, b => buildAction(new DecisionBuilder(b.SetOptions(NodeOptions.DecisionDefault) as NodeBuilder)) ) as IReactiveStructuredActivityBuilder; - public static IReactiveStructuredActivityBuilder AddTokenDecision(this IReactiveStructuredActivityBuilder builder, DecisionBuildAction decisionBuildAction) - where TToken : Token, new() - => builder.AddTokenDecision(ActivityNodeInfo>.Name, decisionBuildAction); + public static IReactiveStructuredActivityBuilder AddDecision(this IReactiveStructuredActivityBuilder builder, DecisionBuildAction decisionBuildAction) + => builder.AddDecision(ActivityNodeInfo>.Name, decisionBuildAction); public static IReactiveStructuredActivityBuilder AddDataStore(this IReactiveStructuredActivityBuilder builder, string dataStoreNodeName, DataStoreBuildAction buildAction) => (builder as BaseActivityBuilder) @@ -97,7 +95,7 @@ public static IReactiveStructuredActivityBuilder AddDataStore(this IReactiveStru dataStoreNodeName, c => { - c.PassAllOn(); + c.PassAllTokensOn(); return Task.CompletedTask; }, b => buildAction(b.SetOptions(NodeOptions.DataStoreDefault) as IDataStoreBuilder) diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/ReactiveStructuredActivityBuilderSpecialsPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/ReactiveStructuredActivityBuilderSpecialsPayloadExtensions.cs deleted file mode 100644 index aa9fd8b8..00000000 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/ReactiveStructuredActivityBuilderSpecialsPayloadExtensions.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Stateflows.Common; -using Stateflows.Activities.Registration.Interfaces; - -namespace Stateflows.Activities.Data -{ - public static class ReactiveStructuredActivityBuilderSpecialsPayloadExtensions - { - public static IReactiveStructuredActivityBuilder AddDataDecision(this IReactiveStructuredActivityBuilder builder, string decisionNodeName, DecisionBuildAction> decisionBuildAction) - => builder.AddTokenDecision>(decisionNodeName, decisionBuildAction); - } -} diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/ReactiveStructuredActivityBuilderTypedExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/ReactiveStructuredActivityBuilderTypedExtensions.cs index 320c2ae2..578e934a 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/ReactiveStructuredActivityBuilderTypedExtensions.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/ReactiveStructuredActivityBuilderTypedExtensions.cs @@ -24,14 +24,16 @@ public static IReactiveStructuredActivityBuilder AddAction(this IReacti return builder.AddAction( actionNodeName, - (ActionDelegateAsync)( c => + (ActionDelegateAsync)(c => { var action = (c as BaseContext).NodeScope.GetAction(c); - InputTokensHolder.Tokens.Value = c.Input; + InputTokensHolder.Tokens.Value = ((ActionContext)c).InputTokens; OutputTokensHolder.Tokens.Value = ((ActionContext)c).OutputTokens; + ActivityNodeContextAccessor.Context.Value = c; var result = action.ExecuteAsync(); + ActivityNodeContextAccessor.Context.Value = null; return result; }), @@ -59,10 +61,12 @@ public static IReactiveStructuredActivityBuilder AddAcceptEventAction(c); - InputTokensHolder.Tokens.Value = c.Input; + InputTokensHolder.Tokens.Value = ((ActionContext)c).InputTokens; OutputTokensHolder.Tokens.Value = ((ActionContext)c).OutputTokens; + ActivityNodeContextAccessor.Context.Value = c; var result = action.ExecuteAsync(); + ActivityNodeContextAccessor.Context.Value = null; return result; }), @@ -89,10 +93,15 @@ private static async Task GetSendEventAction(context); - InputTokensHolder.Tokens.Value = context.Input; + InputTokensHolder.Tokens.Value = ((ActionContext)context).InputTokens; OutputTokensHolder.Tokens.Value = ((ActionContext)context).OutputTokens; - return await callback(action); + + ActivityNodeContextAccessor.Context.Value = context; + var result = await callback(action); + ActivityNodeContextAccessor.Context.Value = null; + + return result; } public static IReactiveStructuredActivityBuilder AddSendEventAction(this IReactiveStructuredActivityBuilder builder, SendEventActionBuildAction buildAction = null) @@ -138,12 +147,10 @@ public static IReactiveStructuredActivityBuilder AddStructuredActivity(this IReactiveStructuredActivityBuilder builder, ParallelActivityBuildAction buildAction = null) - where TToken : Token, new() where TStructuredActivity : ParallelActivityNode => AddParallelActivity(builder, ActivityNodeInfo.Name, buildAction); public static IReactiveStructuredActivityBuilder AddParallelActivity(this IReactiveStructuredActivityBuilder builder, string structuredActivityName, ParallelActivityBuildAction buildAction = null) - where TParallelizationToken : Token, new() where TStructuredActivity : ParallelActivityNode { (builder as IInternal).Services.RegisterStructuredActivity(); @@ -163,12 +170,10 @@ public static IReactiveStructuredActivityBuilder AddParallelActivity(this IReactiveStructuredActivityBuilder builder, IterativeActivityBuildAction buildAction = null, int chunkSize = 1) - where TIterationToken : Token, new() where TStructuredActivity : IterativeActivityNode => AddIterativeActivity(builder, ActivityNodeInfo.Name, buildAction, chunkSize); public static IReactiveStructuredActivityBuilder AddIterativeActivity(this IReactiveStructuredActivityBuilder builder, string structuredActivityName, IterativeActivityBuildAction buildAction = null, int chunkSize = 1) - where TIterationToken : Token, new() where TStructuredActivity : IterativeActivityNode { (builder as IInternal).Services.RegisterStructuredActivity(); diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/ReactiveStructuredActivityBuilderTypedPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/ReactiveStructuredActivityBuilderTypedPayloadExtensions.cs index 25329527..46a68b75 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/ReactiveStructuredActivityBuilderTypedPayloadExtensions.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/ReactiveStructuredActivityBuilder/ReactiveStructuredActivityBuilderTypedPayloadExtensions.cs @@ -24,25 +24,5 @@ public static IReactiveStructuredActivityBuilder AddSendEventAction> => builder.AddSendEventAction, TSendEventAction>(actionNodeName, buildAction); #endregion - - #region AddParallelActivity - public static IReactiveStructuredActivityBuilder AddParallelActivity(this IReactiveStructuredActivityBuilder builder, ParallelActivityBuildAction buildAction = null) - where TStructuredActivity : ParallelActivityNode> - => builder.AddParallelActivity(ActivityNodeInfo.Name, buildAction); - - public static IReactiveStructuredActivityBuilder AddParallelActivity(this IReactiveStructuredActivityBuilder builder, string structuredActivityName, ParallelActivityBuildAction buildAction = null) - where TStructuredActivity : ParallelActivityNode> - => builder.AddParallelActivity, TStructuredActivity>(structuredActivityName, buildAction); - #endregion - - #region AddIterativeActivity - public static IReactiveStructuredActivityBuilder AddIterativeActivity(this IReactiveStructuredActivityBuilder builder, IterativeActivityBuildAction buildAction = null) - where TStructuredActivity : IterativeActivityNode> - => builder.AddIterativeActivity(ActivityNodeInfo.Name, buildAction); - - public static IReactiveStructuredActivityBuilder AddIterativeActivity(this IReactiveStructuredActivityBuilder builder, string structuredActivityName, IterativeActivityBuildAction buildAction = null) - where TStructuredActivity : IterativeActivityNode> - => builder.AddIterativeActivity, TStructuredActivity>(structuredActivityName, buildAction); - #endregion } } diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/Flows/StructuredActivityBuilderFlowsPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/Flows/StructuredActivityBuilderFlowsPayloadExtensions.cs deleted file mode 100644 index 1644be92..00000000 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/Flows/StructuredActivityBuilderFlowsPayloadExtensions.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Stateflows.Common; -using Stateflows.Activities.Registration.Interfaces; - -namespace Stateflows.Activities.Data -{ - public static class StructuredActivityBuilderFlowsPayloadExtensions - { - public static IStructuredActivityBuilder AddDataFlow(this IStructuredActivityBuilder builder, string targetNodeName, ObjectFlowBuildAction> buildAction = null) - => builder.AddFlow>(targetNodeName, buildAction); - } -} diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/Flows/StructuredActivityBuilderFlowsTypedExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/Flows/StructuredActivityBuilderFlowsTypedExtensions.cs index b6c4a6b2..065fe0f0 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/Flows/StructuredActivityBuilderFlowsTypedExtensions.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/Flows/StructuredActivityBuilderFlowsTypedExtensions.cs @@ -1,35 +1,27 @@ -using Stateflows.Common; -using Stateflows.Activities.Registration.Interfaces; +using Stateflows.Activities.Registration.Interfaces; namespace Stateflows.Activities.Typed { public static class StructuredActivityBuilderFlowsTypedExtensions { public static IStructuredActivityBuilder AddFlow(this IStructuredActivityBuilder builder, ObjectFlowBuildAction buildAction = null) - where TToken : Token, new() where TTargetNode : ActivityNode => builder.AddFlow(ActivityNodeInfo.Name, buildAction); - public static IStructuredActivityBuilder AddFlow(this IStructuredActivityBuilder builder, string targetNodeName) - where TToken : Token, new() - where TObjectFlow : Flow - => (builder as IActionBuilder).AddFlow(targetNodeName) as IStructuredActivityBuilder; + public static IStructuredActivityBuilder AddFlow(this IStructuredActivityBuilder builder, string targetNodeName) + where TFlow : Flow + => (builder as IActionBuilder).AddFlow(targetNodeName) as IStructuredActivityBuilder; public static IStructuredActivityBuilder AddFlow(this IStructuredActivityBuilder builder) - where TToken : Token, new() where TFlow : Flow where TTargetNode : ActivityNode => builder.AddFlow(ActivityNodeInfo.Name); public static IStructuredActivityBuilder AddFlow(this IStructuredActivityBuilder builder, string targetNodeName) - where TToken : Token, new() - where TTransformedToken : Token, new() where TFlow : TransformationFlow => (builder as IActionBuilder).AddFlow(targetNodeName) as IStructuredActivityBuilder; public static IStructuredActivityBuilder AddFlow(this IStructuredActivityBuilder builder) - where TToken : Token, new() - where TTransformedToken : Token, new() where TFlow : TransformationFlow where TTargetNode : ActivityNode => builder.AddFlow(ActivityNodeInfo.Name); diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/Flows/StructuredActivityBuilderFlowsTypedPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/Flows/StructuredActivityBuilderFlowsTypedPayloadExtensions.cs deleted file mode 100644 index e6074f47..00000000 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/Flows/StructuredActivityBuilderFlowsTypedPayloadExtensions.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Stateflows.Common; -using Stateflows.Activities.Registration.Interfaces; - -namespace Stateflows.Activities.Typed.Data -{ - public static class StructuredActivityBuilderFlowsTypedPayloadExtensions - { - public static IStructuredActivityBuilder AddDataFlow(this IStructuredActivityBuilder builder, ObjectFlowBuildAction> buildAction = null) - where TTargetNode : ActivityNode - => builder.AddFlow>(ActivityNodeInfo.Name, buildAction); - - public static IStructuredActivityBuilder AddDataFlow(this IStructuredActivityBuilder builder, string targetNodeName) - where TObjectFlow : Flow> - => (builder as IActionBuilder).AddFlow, TObjectFlow>(targetNodeName) as IStructuredActivityBuilder; - - public static IStructuredActivityBuilder AddDataFlow(this IStructuredActivityBuilder builder) - where TFlow : Flow> - where TTargetNode : ActivityNode - => builder.AddFlow, TFlow>(ActivityNodeInfo.Name); - - public static IStructuredActivityBuilder AddDataFlow(this IStructuredActivityBuilder builder, string targetNodeName) - where TFlow : TransformationFlow, Token> - => (builder as IActionBuilder).AddFlow, Token, TFlow>(targetNodeName) as IStructuredActivityBuilder; - - public static IStructuredActivityBuilder AddDataFlow(this IStructuredActivityBuilder builder) - where TFlow : TransformationFlow, Token> - where TTargetNode : ActivityNode - => builder.AddFlow, Token, TFlow>(ActivityNodeInfo.Name); - } -} diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/StructuredActivityBuilderAnonymousExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/StructuredActivityBuilderAnonymousExtensions.cs index 82068789..90ae78e8 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/StructuredActivityBuilderAnonymousExtensions.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/StructuredActivityBuilderAnonymousExtensions.cs @@ -9,11 +9,9 @@ public static IStructuredActivityBuilder AddStructuredActivity(this IStructuredA => builder.AddStructuredActivity(ActivityNodeInfo.Name, buildAction); public static IStructuredActivityBuilder AddParallelActivity(this IStructuredActivityBuilder builder, ParallelActivityBuildAction buildAction) - where TParallelizationToken : Token, new() => builder.AddParallelActivity(ActivityNodeInfo>.Name, buildAction); public static IStructuredActivityBuilder AddIterativeActivity(this IStructuredActivityBuilder builder, IterativeActivityBuildAction buildAction) - where TIterationToken : Token, new() => builder.AddIterativeActivity(ActivityNodeInfo>.Name, buildAction); } } diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/StructuredActivityBuilderSpecialsExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/StructuredActivityBuilderSpecialsExtensions.cs index 15a8e958..8855c974 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/StructuredActivityBuilderSpecialsExtensions.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/StructuredActivityBuilderSpecialsExtensions.cs @@ -1,9 +1,7 @@ using System.Threading.Tasks; -using Stateflows.Common; using Stateflows.Activities.Registration; using Stateflows.Activities.Registration.Builders; using Stateflows.Activities.Registration.Interfaces; -using Stateflows.Common.Classes; namespace Stateflows.Activities { @@ -16,7 +14,7 @@ public static IStructuredActivityBuilder AddJoin(this IStructuredActivityBuilder joinNodeName, c => { - c.PassAllOn(); + c.PassAllTokensOn(); return Task.CompletedTask; }, b => joinBuildAction(b) @@ -32,7 +30,7 @@ public static IStructuredActivityBuilder AddFork(this IStructuredActivityBuilder forkNodeName, c => { - c.PassAllOn(); + c.PassAllTokensOn(); return Task.CompletedTask; }, b => forkBuildAction(b) @@ -48,7 +46,7 @@ public static IStructuredActivityBuilder AddMerge(this IStructuredActivityBuilde mergeNodeName, c => { - c.PassAllOn(); + c.PassAllTokensOn(); return Task.CompletedTask; }, b => mergeBuildAction(b.SetOptions(NodeOptions.None) as IMergeBuilder) @@ -64,32 +62,30 @@ public static IStructuredActivityBuilder AddControlDecision(this IStructuredActi decisionNodeName, c => { - c.PassAllOn(); + c.PassAllTokensOn(); return Task.CompletedTask; }, b => decisionBuildAction(b.SetOptions(NodeOptions.DecisionDefault) as IDecisionBuilder) ) as IStructuredActivityBuilder; public static IStructuredActivityBuilder AddControlDecision(this IStructuredActivityBuilder builder, DecisionBuildAction decisionBuildAction) - => builder.AddControlDecision(ActivityNodeInfo>.Name, decisionBuildAction); + => builder.AddControlDecision(ActivityNodeInfo>.Name, decisionBuildAction); - public static IStructuredActivityBuilder AddTokenDecision(this IStructuredActivityBuilder builder, string decisionNodeName, DecisionBuildAction decisionBuildAction) - where TToken : Token, new() + public static IStructuredActivityBuilder AddDecision(this IStructuredActivityBuilder builder, string decisionNodeName, DecisionBuildAction decisionBuildAction) => (builder as BaseActivityBuilder) .AddNode( NodeType.Decision, decisionNodeName, c => { - c.PassAllOn(); + c.PassAllTokensOn(); return Task.CompletedTask; }, b => decisionBuildAction(new DecisionBuilder(b.SetOptions(NodeOptions.DecisionDefault) as NodeBuilder)) ) as IStructuredActivityBuilder; - public static IStructuredActivityBuilder AddTokenDecision(this IStructuredActivityBuilder builder, DecisionBuildAction decisionBuildAction) - where TToken : Token, new() - => builder.AddTokenDecision(ActivityNodeInfo>.Name, decisionBuildAction); + public static IStructuredActivityBuilder AddDecision(this IStructuredActivityBuilder builder, DecisionBuildAction decisionBuildAction) + => builder.AddDecision(ActivityNodeInfo>.Name, decisionBuildAction); public static IStructuredActivityBuilder AddDataStore(this IStructuredActivityBuilder builder, string dataStoreNodeName, DataStoreBuildAction decisionBuildAction) => (builder as BaseActivityBuilder) @@ -98,7 +94,7 @@ public static IStructuredActivityBuilder AddDataStore(this IStructuredActivityBu dataStoreNodeName, c => { - c.PassAllOn(); + c.PassAllTokensOn(); return Task.CompletedTask; }, b => decisionBuildAction(b.SetOptions(NodeOptions.DataStoreDefault) as IDataStoreBuilder) diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/StructuredActivityBuilderSpecialsPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/StructuredActivityBuilderSpecialsPayloadExtensions.cs deleted file mode 100644 index 46cf3a0a..00000000 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/StructuredActivityBuilderSpecialsPayloadExtensions.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Stateflows.Common; -using Stateflows.Activities.Registration.Interfaces; - -namespace Stateflows.Activities.Data -{ - public static class StructuredActivityBuilderSpecialsPayloadExtensions - { - public static IStructuredActivityBuilder AddDataDecision(this IStructuredActivityBuilder builder, string decisionNodeName, DecisionBuildAction> decisionBuildAction) - => builder.AddTokenDecision>(decisionNodeName, decisionBuildAction); - } -} diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/StructuredActivityBuilderTypedExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/StructuredActivityBuilderTypedExtensions.cs index 4f3dedfa..5eb55606 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/StructuredActivityBuilderTypedExtensions.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/StructuredActivityBuilderTypedExtensions.cs @@ -28,10 +28,12 @@ public static IStructuredActivityBuilder AddAction(this IStructuredActi { var action = (c as BaseContext).NodeScope.GetAction(c); - InputTokensHolder.Tokens.Value = c.Input; + InputTokensHolder.Tokens.Value = ((ActionContext)c).InputTokens; OutputTokensHolder.Tokens.Value = ((ActionContext)c).OutputTokens; + ActivityNodeContextAccessor.Context.Value = c; var result = action.ExecuteAsync(); + ActivityNodeContextAccessor.Context.Value = null; return result; }), @@ -51,10 +53,14 @@ private static async Task GetSendEventAction(context); - InputTokensHolder.Tokens.Value = context.Input; + InputTokensHolder.Tokens.Value = ((ActionContext)context).InputTokens; OutputTokensHolder.Tokens.Value = ((ActionContext)context).OutputTokens; - return await callback(action); + ActivityNodeContextAccessor.Context.Value = context; + var result = await callback(action); + ActivityNodeContextAccessor.Context.Value = null; + + return result; } public static IStructuredActivityBuilder AddSendEventAction(this IStructuredActivityBuilder builder, SendEventActionBuildAction buildAction = null) @@ -123,12 +129,12 @@ public static IStructuredActivityBuilder AddStructuredActivity(this IStructuredActivityBuilder builder, ParallelActivityBuildAction buildAction = null) - where TParallelizationToken : Token, new() + where TParallelizationToken : TokenHolder, new() where TStructuredActivity : ParallelActivityNode => AddParallelActivity(builder, ActivityNodeInfo.Name, buildAction); public static IStructuredActivityBuilder AddParallelActivity(this IStructuredActivityBuilder builder, string structuredActivityName, ParallelActivityBuildAction buildAction = null) - where TParallelizationToken : Token, new() + where TParallelizationToken : TokenHolder, new() where TStructuredActivity : ParallelActivityNode { (builder as IInternal).Services.RegisterStructuredActivity(); @@ -148,12 +154,12 @@ public static IStructuredActivityBuilder AddParallelActivity(this IStructuredActivityBuilder builder, IterativeActivityBuildAction buildAction = null) - where TIterationToken : Token, new() + where TIterationToken : TokenHolder, new() where TStructuredActivity : IterativeActivityNode => AddIterativeActivity(builder, ActivityNodeInfo.Name, buildAction); public static IStructuredActivityBuilder AddIterativeActivity(this IStructuredActivityBuilder builder, string structuredActivityName, IterativeActivityBuildAction buildAction = null) - where TIterationToken : Token, new() + where TIterationToken : TokenHolder, new() where TStructuredActivity : IterativeActivityNode { (builder as IInternal).Services.RegisterStructuredActivity(); diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/StructuredActivityBuilderTypedPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/StructuredActivityBuilderTypedPayloadExtensions.cs index 1450f89b..046c4d1d 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/StructuredActivityBuilderTypedPayloadExtensions.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/StructuredActivityBuilder/StructuredActivityBuilderTypedPayloadExtensions.cs @@ -14,25 +14,5 @@ public static IStructuredActivityBuilder AddSendEventAction> => builder.AddSendEventAction, TSendEventAction>(actionNodeName, buildAction); #endregion - - #region AddParallelActivity - public static IStructuredActivityBuilder AddParallelActivity(this IStructuredActivityBuilder builder, ParallelActivityBuildAction buildAction = null) - where TStructuredActivity : ParallelActivityNode> - => builder.AddParallelActivity(ActivityNodeInfo.Name, buildAction); - - public static IStructuredActivityBuilder AddParallelActivity(this IStructuredActivityBuilder builder, string structuredActivityName, ParallelActivityBuildAction buildAction = null) - where TStructuredActivity : ParallelActivityNode> - => builder.AddParallelActivity, TStructuredActivity>(structuredActivityName, buildAction); - #endregion - - #region AddIterativeActivity - public static IStructuredActivityBuilder AddIterativeActivity(this IStructuredActivityBuilder builder, IterativeActivityBuildAction buildAction = null) - where TStructuredActivity : IterativeActivityNode> - => builder.AddIterativeActivity(ActivityNodeInfo.Name, buildAction); - - public static IStructuredActivityBuilder AddIterativeActivity(this IStructuredActivityBuilder builder, string structuredActivityName, IterativeActivityBuildAction buildAction = null) - where TStructuredActivity : IterativeActivityNode> - => builder.AddIterativeActivity, TStructuredActivity>(structuredActivityName, buildAction); - #endregion } } diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/TypedActionBuilder/Flows/TypedActionBuilderFlowsPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/TypedActionBuilder/Flows/TypedActionBuilderFlowsPayloadExtensions.cs deleted file mode 100644 index 1342b33a..00000000 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/TypedActionBuilder/Flows/TypedActionBuilderFlowsPayloadExtensions.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Stateflows.Common; -using Stateflows.Activities.Registration.Interfaces; - -namespace Stateflows.Activities.Data -{ - public static class TypedActionBuilderFlowsPayloadExtensions - { - public static ITypedActionBuilder AddDataFlow(this ITypedActionBuilder builder, string targetNodeName, ObjectFlowBuildAction> buildAction = null) - => builder.AddFlow>(targetNodeName, buildAction); - } -} diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/TypedActionBuilder/Flows/TypedActionBuilderFlowsTypedExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/TypedActionBuilder/Flows/TypedActionBuilderFlowsTypedExtensions.cs index 521937bc..ea109759 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/TypedActionBuilder/Flows/TypedActionBuilderFlowsTypedExtensions.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/TypedActionBuilder/Flows/TypedActionBuilderFlowsTypedExtensions.cs @@ -1,35 +1,27 @@ using Stateflows.Activities.Registration.Interfaces; -using Stateflows.Common; namespace Stateflows.Activities.Typed { public static class TypedActionBuilderFlowsTypedExtensions { public static ITypedActionBuilder AddFlow(this ITypedActionBuilder builder, ObjectFlowBuildAction buildAction = null) - where TToken : Token, new() where TTargetNode : ActivityNode => builder.AddFlow(ActivityNodeInfo.Name, buildAction); - public static ITypedActionBuilder AddFlow(this ITypedActionBuilder builder, string targetNodeName) - where TToken : Token, new() - where TObjectFlow : Flow - => (builder as IActionBuilder).AddFlow(targetNodeName) as ITypedActionBuilder; + public static ITypedActionBuilder AddFlow(this ITypedActionBuilder builder, string targetNodeName) + where TFlow : Flow + => (builder as IActionBuilder).AddFlow(targetNodeName) as ITypedActionBuilder; public static ITypedActionBuilder AddFlow(this ITypedActionBuilder builder) - where TToken : Token, new() where TFlow : Flow where TTargetNode : ActivityNode => builder.AddFlow(ActivityNodeInfo.Name); public static ITypedActionBuilder AddFlow(this ITypedActionBuilder builder, string targetNodeName) - where TToken : Token, new() - where TTransformedToken : Token, new() where TFlow : TransformationFlow => (builder as IActionBuilder).AddFlow(targetNodeName) as ITypedActionBuilder; public static ITypedActionBuilder AddFlow(this ITypedActionBuilder builder) - where TToken : Token, new() - where TTransformedToken : Token, new() where TFlow : TransformationFlow where TTargetNode : ActivityNode => builder.AddFlow(ActivityNodeInfo.Name); diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/TypedActionBuilder/Flows/TypedActionBuilderFlowsTypedPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/TypedActionBuilder/Flows/TypedActionBuilderFlowsTypedPayloadExtensions.cs deleted file mode 100644 index ea69e08d..00000000 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/TypedActionBuilder/Flows/TypedActionBuilderFlowsTypedPayloadExtensions.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Stateflows.Common; -using Stateflows.Activities.Registration.Interfaces; - -namespace Stateflows.Activities.Typed.Data -{ - public static class TypedActionBuilderFlowsTypedPayloadExtensions - { - public static ITypedActionBuilder AddDataFlow(this ITypedActionBuilder builder, ObjectFlowBuildAction> buildAction = null) - where TTargetNode : ActivityNode - => builder.AddFlow>(ActivityNodeInfo.Name, buildAction); - - public static ITypedActionBuilder AddDataFlow(this ITypedActionBuilder builder, string targetNodeName) - where TObjectFlow : Flow> - => (builder as IActionBuilder).AddFlow, TObjectFlow>(targetNodeName) as ITypedActionBuilder; - - public static ITypedActionBuilder AddDataFlow(this ITypedActionBuilder builder) - where TFlow : Flow> - where TTargetNode : ActivityNode - => builder.AddFlow, TFlow>(ActivityNodeInfo.Name); - - public static ITypedActionBuilder AddDataFlow(this ITypedActionBuilder builder, string targetNodeName) - where TFlow : TransformationFlow, Token> - => (builder as IActionBuilder).AddFlow, Token, TFlow>(targetNodeName) as ITypedActionBuilder; - - public static ITypedActionBuilder AddDataFlow(this ITypedActionBuilder builder) - where TFlow : TransformationFlow, Token> - where TTargetNode : ActivityNode - => builder.AddFlow, Token, TFlow>(ActivityNodeInfo.Name); - } -} diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/TypedActivityBuilder/TypedActivityBuilderSpecialsExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/TypedActivityBuilder/TypedActivityBuilderSpecialsExtensions.cs index 16aaa298..67465047 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/TypedActivityBuilder/TypedActivityBuilderSpecialsExtensions.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/TypedActivityBuilder/TypedActivityBuilderSpecialsExtensions.cs @@ -15,7 +15,7 @@ public static ITypedActivityBuilder AddJoin(this ITypedActivityBuilder builder, joinNodeName, c => { - c.PassAllOn(); + c.PassAllTokensOn(); return Task.CompletedTask; }, b => joinBuildAction(b) @@ -28,7 +28,7 @@ public static ITypedActivityBuilder AddFork(this ITypedActivityBuilder builder, forkNodeName, c => { - c.PassAllOn(); + c.PassAllTokensOn(); return Task.CompletedTask; }, b => forkBuildAction(b) @@ -41,7 +41,7 @@ public static ITypedActivityBuilder AddMerge(this ITypedActivityBuilder builder, mergeNodeName, c => { - c.PassAllOn(); + c.PassAllTokensOn(); return Task.CompletedTask; }, b => mergeBuildAction(b.SetOptions(NodeOptions.None) as IMergeBuilder) @@ -54,21 +54,20 @@ public static ITypedActivityBuilder AddControlDecision(this ITypedActivityBuilde decisionNodeName, c => { - c.PassAllOn(); + c.PassAllTokensOn(); return Task.CompletedTask; }, b => decisionBuildAction(b.SetOptions(NodeOptions.DecisionDefault) as IDecisionBuilder) ) as ITypedActivityBuilder; - public static ITypedActivityBuilder AddTokenDecision(this ITypedActivityBuilder builder, string decisionNodeName, DecisionBuildAction decisionBuildAction) - where TToken : Token, new() + public static ITypedActivityBuilder AddDecision(this ITypedActivityBuilder builder, string decisionNodeName, DecisionBuildAction decisionBuildAction) => (builder as BaseActivityBuilder) .AddNode( NodeType.Decision, decisionNodeName, c => { - c.PassAllOn(); + c.PassAllTokensOn(); return Task.CompletedTask; }, b => decisionBuildAction(new DecisionBuilder(b.SetOptions(NodeOptions.DecisionDefault) as NodeBuilder)) @@ -81,7 +80,7 @@ public static ITypedActivityBuilder AddDataStore(this ITypedActivityBuilder buil dataStoreNodeName, c => { - c.PassAllOn(); + c.PassAllTokensOn(); return Task.CompletedTask; }, b => decisionBuildAction(b.SetOptions(NodeOptions.DataStoreDefault) as IDataStoreBuilder) diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/TypedActivityBuilder/TypedActivityBuilderSpecialsPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/TypedActivityBuilder/TypedActivityBuilderSpecialsPayloadExtensions.cs deleted file mode 100644 index 11140d8d..00000000 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/TypedActivityBuilder/TypedActivityBuilderSpecialsPayloadExtensions.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Stateflows.Common; -using Stateflows.Activities.Registration.Interfaces; - -namespace Stateflows.Activities.Data -{ - public static class TypedActivityBuilderSpecialsPayloadExtensions - { - public static ITypedActivityBuilder AddDataDecision(this ITypedActivityBuilder builder, string decisionNodeName, DecisionBuildAction> decisionBuildAction) - => builder.AddTokenDecision>(decisionNodeName, decisionBuildAction); - } -} diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/TypedActivityBuilder/TypedActivityBuilderTypedExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/TypedActivityBuilder/TypedActivityBuilderTypedExtensions.cs index b89bf70a..2b055d0a 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/TypedActivityBuilder/TypedActivityBuilderTypedExtensions.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/TypedActivityBuilder/TypedActivityBuilderTypedExtensions.cs @@ -28,10 +28,12 @@ public static ITypedActivityBuilder AddAction(this ITypedActivityBuilde { var action = (c as BaseContext).NodeScope.GetAction(c); - InputTokensHolder.Tokens.Value = c.Input; + InputTokensHolder.Tokens.Value = ((ActionContext)c).InputTokens; OutputTokensHolder.Tokens.Value = ((ActionContext)c).OutputTokens; + ActivityNodeContextAccessor.Context.Value = c; var result = action.ExecuteAsync(); + ActivityNodeContextAccessor.Context.Value = null; return result; }), @@ -59,10 +61,12 @@ public static ITypedActivityBuilder AddAcceptEventAction(c); - InputTokensHolder.Tokens.Value = c.Input; + InputTokensHolder.Tokens.Value = ((ActionContext)c).InputTokens; OutputTokensHolder.Tokens.Value = ((ActionContext)c).OutputTokens; + ActivityNodeContextAccessor.Context.Value = c; var result = action.ExecuteAsync(); + ActivityNodeContextAccessor.Context.Value = null; return result; }), @@ -77,10 +81,14 @@ private static async Task GetSendEventAction(context); - InputTokensHolder.Tokens.Value = context.Input; + InputTokensHolder.Tokens.Value = ((ActionContext)context).InputTokens; OutputTokensHolder.Tokens.Value = ((ActionContext)context).OutputTokens; - return await callback(action); + ActivityNodeContextAccessor.Context.Value = context; + var result = await callback(action); + ActivityNodeContextAccessor.Context.Value = null; + + return result; } public static ITypedActivityBuilder AddSendEventAction(this ITypedActivityBuilder builder, SendEventActionBuildAction buildAction = null) @@ -126,12 +134,10 @@ public static ITypedActivityBuilder AddStructuredActivity(t #region AddParallelActivity public static ITypedActivityBuilder AddParallelActivity(this ITypedActivityBuilder builder, ParallelActivityBuildAction buildAction = null) - where TParallelizationToken : Token, new() where TStructuredActivity : StructuredActivityNode => AddParallelActivity(builder, ActivityNodeInfo.Name, buildAction); public static ITypedActivityBuilder AddParallelActivity(this ITypedActivityBuilder builder, string structuredActivityName, ParallelActivityBuildAction buildAction = null) - where TParallelizationToken : Token, new() where TStructuredActivity : StructuredActivityNode { (builder as IInternal).Services.RegisterStructuredActivity(); @@ -151,12 +157,10 @@ public static ITypedActivityBuilder AddParallelActivity(this ITypedActivityBuilder builder, IterativeActivityBuildAction buildAction = null, int chunkSize = 1) - where TIterationToken : Token, new() where TStructuredActivity : StructuredActivityNode => AddIterativeActivity(builder, ActivityNodeInfo.Name, buildAction, chunkSize); public static ITypedActivityBuilder AddIterativeActivity(this ITypedActivityBuilder builder, string structuredActivityName, IterativeActivityBuildAction buildAction = null, int chunkSize = 1) - where TIterationToken : Token, new() where TStructuredActivity : StructuredActivityNode { (builder as IInternal).Services.RegisterStructuredActivity(); diff --git a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/TypedActivityBuilder/TypedActivityBuilderTypedPayloadExtensions.cs b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/TypedActivityBuilder/TypedActivityBuilderTypedPayloadExtensions.cs index 7e73100a..ba3de41e 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/Extensions/TypedActivityBuilder/TypedActivityBuilderTypedPayloadExtensions.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/Extensions/TypedActivityBuilder/TypedActivityBuilderTypedPayloadExtensions.cs @@ -24,25 +24,5 @@ public static ITypedActivityBuilder AddSendEventAction> => builder.AddSendEventAction, TSendEventAction>(actionNodeName, buildAction); #endregion - - #region AddParallelActivity - public static ITypedActivityBuilder AddParallelActivity(this ITypedActivityBuilder builder, ParallelActivityBuildAction buildAction = null) - where TStructuredActivity : StructuredActivityNode> - => builder.AddParallelActivity(ActivityNodeInfo.Name, buildAction); - - public static ITypedActivityBuilder AddParallelActivity(this ITypedActivityBuilder builder, string structuredActivityName, ParallelActivityBuildAction buildAction = null) - where TStructuredActivity : StructuredActivityNode> - => builder.AddParallelActivity, TStructuredActivity>(structuredActivityName, buildAction); - #endregion - - #region AddIterativeActivity - public static ITypedActivityBuilder AddIterativeActivity(this ITypedActivityBuilder builder, IterativeActivityBuildAction buildAction = null) - where TStructuredActivity : StructuredActivityNode> - => builder.AddIterativeActivity(ActivityNodeInfo.Name, buildAction); - - public static ITypedActivityBuilder AddIterativeActivity(this ITypedActivityBuilder builder, string structuredActivityName, IterativeActivityBuildAction buildAction = null) - where TStructuredActivity : StructuredActivityNode> - => builder.AddIterativeActivity, TStructuredActivity>(structuredActivityName, buildAction); - #endregion } } diff --git a/Core/Stateflows/Activities/Registration/Interfaces/IActivityBuilder.cs b/Core/Stateflows/Activities/Registration/Interfaces/IActivityBuilder.cs index e1ee8714..8d56f85d 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/IActivityBuilder.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/IActivityBuilder.cs @@ -3,6 +3,7 @@ namespace Stateflows.Activities.Registration.Interfaces { public interface IActivityBuilder : + IActivityUtils, IReactiveActivity, IActivityEvents, IInitial, @@ -14,6 +15,7 @@ public interface IActivityBuilder : { } public interface ITypedActivityBuilder : + IActivityUtils, IReactiveActivity, IInitial, IFinal, diff --git a/Core/Stateflows/Activities/Registration/Interfaces/IDecisionBuilder.cs b/Core/Stateflows/Activities/Registration/Interfaces/IDecisionBuilder.cs index 264bd9c3..01fa10ce 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/IDecisionBuilder.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/IDecisionBuilder.cs @@ -1,10 +1,8 @@ using Stateflows.Activities.Registration.Interfaces.Base; -using Stateflows.Common; namespace Stateflows.Activities { public interface IDecisionBuilder : IDecisionFlow>, IElseDecisionFlow> - where TToken : Token, new() { } public interface IDecisionBuilder : IDecisionFlow, IElseDecisionFlow diff --git a/Core/Stateflows/Activities/Registration/Interfaces/IFlowBuilder.cs b/Core/Stateflows/Activities/Registration/Interfaces/IFlowBuilder.cs index 639e8ed4..822f4fa2 100644 --- a/Core/Stateflows/Activities/Registration/Interfaces/IFlowBuilder.cs +++ b/Core/Stateflows/Activities/Registration/Interfaces/IFlowBuilder.cs @@ -1,42 +1,33 @@ -using Stateflows.Common; - -namespace Stateflows.Activities.Registration.Interfaces +namespace Stateflows.Activities.Registration.Interfaces { public interface IObjectFlowBuilder : IFlowWeight>, IObjectFlowGuardBuilderBase>, IObjectFlowTransformationBuilderBase> - where TToken : Token, new() { } public interface IObjectFlowBuilderWithWeight : IObjectFlowGuardBuilderBase>, IObjectFlowTransformationBuilderBase> - where TToken : Token, new() { } public interface IElseObjectFlowBuilderWithWeight : IObjectFlowTransformationBuilderBase> - where TToken : Token, new() { } public interface IElseObjectFlowBuilder : IFlowWeight>, IObjectFlowTransformationBuilderBase> - where TToken : Token, new() { } public interface IObjectFlowGuardBuilderBase - where TToken : Token, new() { TReturn AddGuard(GuardDelegateAsync guardAsync); } public interface IObjectFlowTransformationBuilderBase - where TToken : Token, new() { - TReturn AddTransformation(TransformationDelegateAsync transformationAsync) - where TTransformedToken : Token, new(); + TReturn AddTransformation(TransformationDelegateAsync transformationAsync); } public interface IControlFlowBuilderBase diff --git a/Core/Stateflows/Activities/StateMachines/Classes/IntegratedActivityBuilder.cs b/Core/Stateflows/Activities/StateMachines/Classes/IntegratedActivityBuilder.cs index 88edc667..ab29b3d0 100644 --- a/Core/Stateflows/Activities/StateMachines/Classes/IntegratedActivityBuilder.cs +++ b/Core/Stateflows/Activities/StateMachines/Classes/IntegratedActivityBuilder.cs @@ -20,7 +20,7 @@ public SubscriptionRequest GetSubscriptionRequest() => new SubscriptionRequest() { NotificationNames = Notifications - .Select(notificationType => EventInfo.GetName(notificationType)) + .Select(notificationType => notificationType.GetEventName()) .ToList() }; @@ -28,7 +28,7 @@ public UnsubscriptionRequest GetUnsubscriptionRequest() => new UnsubscriptionRequest() { NotificationNames = Notifications - .Select(notificationType => EventInfo.GetName(notificationType)) + .Select(notificationType => notificationType.GetEventName()) .ToList() }; diff --git a/Core/Stateflows/Activities/StateMachines/Extensions/CompositeStateBuilderExtensions.cs b/Core/Stateflows/Activities/StateMachines/Extensions/CompositeStateBuilderExtensions.cs index e419e4ed..3d681a3a 100644 --- a/Core/Stateflows/Activities/StateMachines/Extensions/CompositeStateBuilderExtensions.cs +++ b/Core/Stateflows/Activities/StateMachines/Extensions/CompositeStateBuilderExtensions.cs @@ -26,21 +26,9 @@ public static ICompositeStateBuilder AddOnEntryActivity(this ICompositeStateBuil return a.SendCompoundAsync( integratedActivityBuilder.GetSubscriptionRequest(), new ResetRequest() { KeepVersion = true }, - new ExecutionRequest(initializationRequest, new List()), + new ExecutionRequest(initializationRequest, new List()), integratedActivityBuilder.GetUnsubscriptionRequest() ); - //var request = new CompoundRequest() - //{ - // Events = new List() - // { - // integratedActivityBuilder.GetSubscriptionRequest(), - // new ResetRequest() { KeepVersion = true }, - // new ExecutionRequest(initializationRequest, new List()), - // integratedActivityBuilder.GetUnsubscriptionRequest(), - // } - //}; - - //return a.RequestAsync(request); }); } } @@ -64,21 +52,9 @@ public static ICompositeStateBuilder AddOnExitActivity(this ICompositeStateBuild return a.SendCompoundAsync( integratedActivityBuilder.GetSubscriptionRequest(), new ResetRequest() { KeepVersion = true }, - new ExecutionRequest(initializationRequest, new List()), + new ExecutionRequest(initializationRequest, new List()), integratedActivityBuilder.GetUnsubscriptionRequest() ); - //var request = new CompoundRequest() - //{ - // Events = new List() - // { - // integratedActivityBuilder.GetSubscriptionRequest(), - // new ResetRequest() { KeepVersion = true }, - // new ExecutionRequest(initializationRequest, new List()), - // integratedActivityBuilder.GetUnsubscriptionRequest(), - // } - //}; - - //return a.RequestAsync(request); }); } } diff --git a/Core/Stateflows/Activities/StateMachines/Extensions/StateBuilderExtensions.cs b/Core/Stateflows/Activities/StateMachines/Extensions/StateBuilderExtensions.cs index 0f7546d2..bba13366 100644 --- a/Core/Stateflows/Activities/StateMachines/Extensions/StateBuilderExtensions.cs +++ b/Core/Stateflows/Activities/StateMachines/Extensions/StateBuilderExtensions.cs @@ -29,21 +29,9 @@ public static IStateBuilder AddOnEntryActivity(this IStateBuilder builder, strin return a.SendCompoundAsync( integratedActivityBuilder.GetSubscriptionRequest(), new ResetRequest() { KeepVersion = true }, - new ExecutionRequest(initializationRequest, new List()), + new ExecutionRequest(initializationRequest, new List()), integratedActivityBuilder.GetUnsubscriptionRequest() ); - //var request = new CompoundRequest() - //{ - // Events = new List() - // { - // integratedActivityBuilder.GetSubscriptionRequest(), - // new ResetRequest() { KeepVersion = true }, - // new ExecutionRequest(initializationRequest, new List()), - // integratedActivityBuilder.GetUnsubscriptionRequest(), - // } - //}; - - //return a.RequestAsync(request); }); } } @@ -68,7 +56,7 @@ public static IStateBuilder AddOnExitActivity(this IStateBuilder builder, string return a.SendCompoundAsync( integratedActivityBuilder.GetSubscriptionRequest(), new ResetRequest() { KeepVersion = true }, - new ExecutionRequest(initializationRequest, new List()), + new ExecutionRequest(initializationRequest, new List()), integratedActivityBuilder.GetUnsubscriptionRequest() ); //var request = new CompoundRequest() diff --git a/Core/Stateflows/Activities/StateMachines/Extensions/TransitionBuilderExtensions.cs b/Core/Stateflows/Activities/StateMachines/Extensions/TransitionBuilderExtensions.cs index ffc0ce45..2bb867f7 100644 --- a/Core/Stateflows/Activities/StateMachines/Extensions/TransitionBuilderExtensions.cs +++ b/Core/Stateflows/Activities/StateMachines/Extensions/TransitionBuilderExtensions.cs @@ -15,7 +15,7 @@ public static ITransitionBuilder AddGuardActivity(this ITransiti where TEvent : Event, new() => builder.AddGuard( async c => c.TryLocateActivity(activityName, Constants.Guard, out var a) - && ((await a.ExecuteAsync(parametersBuilder?.Invoke(c), new Token[] { c.Event })).Response?.OutputTokens.OfType>().FirstOrDefault()?.Payload ?? false) + && ((await a.ExecuteAsync(parametersBuilder?.Invoke(c), new object[] { c.Event })).Response?.OutputTokens.OfType().FirstOrDefault() ?? false) ); [DebuggerHidden] @@ -34,7 +34,7 @@ public static ITransitionBuilder AddEffectActivity(this ITransit { if (c.TryLocateActivity(activityName, Constants.Guard, out var a)) { - await a.ExecuteAsync(parametersBuilder?.Invoke(c), new Token[] { c.Event }); + await a.ExecuteAsync(parametersBuilder?.Invoke(c), new object[] { c.Event }); } } ); diff --git a/Core/Stateflows/Activities/Streams/NodeStreams.cs b/Core/Stateflows/Activities/Streams/NodeStreams.cs deleted file mode 100644 index f7ebc534..00000000 --- a/Core/Stateflows/Activities/Streams/NodeStreams.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System.Collections.Generic; -using Newtonsoft.Json; -using Stateflows.Activities.Models; - -namespace Stateflows.Activities.Streams -{ - //internal class NodeStreams - //{ - // public string NodeIdentifier { get; set; } - - // [JsonIgnore] - // public Graph Graph { get; private set; } - - // [JsonIgnore] - // private Node node = null; - - // [JsonIgnore] - // public Node Node - // { - // get - // { - // if (node is null && Graph.AllNodes.TryGetValue(NodeIdentifier, out Node e)) - // { - // node = e; - // } - - // return node; - // } - // } - - // public Dictionary Inputs { get; set; } = new Dictionary(); - - // [JsonIgnore] - // public Dictionary Outputs { get; set; } = new Dictionary(); - - // //public void Output(TToken token) - // // where TToken : Token, new(); - // //{ - // // var controlTokenName = TokenInfo.Name; - // // var tokenName = token.Name; - - // // foreach (var edgeOutput in Outputs) - // // { - // // var edgeTokenName = edgeOutput.Key.TokenType.GetTokenName(); - - // // if ( - // // (edgeTokenName == TokenInfo.Name) || - // // (edgeTokenName != controlTokenName && tokenName == controlTokenName) - // // ) - // // { - // // edgeOutput.Value.Consume(token); - // // } - // // } - // //} - //} -} diff --git a/Core/Stateflows/Activities/Streams/Stream.cs b/Core/Stateflows/Activities/Streams/Stream.cs index 438cfd1a..7d55f591 100644 --- a/Core/Stateflows/Activities/Streams/Stream.cs +++ b/Core/Stateflows/Activities/Streams/Stream.cs @@ -11,9 +11,9 @@ public class Stream public bool IsPersistent { get; set; } = false; - public Queue Tokens { get; set; } = new Queue(); + public Queue Tokens { get; set; } = new Queue(); - public void Consume(IEnumerable tokens, bool isPersistent) + public void Consume(IEnumerable tokens, bool isPersistent) { IsPersistent = isPersistent; foreach (var token in tokens) @@ -22,10 +22,9 @@ public void Consume(IEnumerable tokens, bool isPersistent) } } - public void Consume(TToken token) - where TToken : Token, new() + public void Consume(TokenHolder token) { - if (token is ControlToken) + if (token is TokenHolder) { IsActivated = true; } diff --git a/Core/Stateflows/Activities/Tokens/Control.cs b/Core/Stateflows/Activities/Tokens/Control.cs new file mode 100644 index 00000000..dd220ae2 --- /dev/null +++ b/Core/Stateflows/Activities/Tokens/Control.cs @@ -0,0 +1,5 @@ +namespace Stateflows.Activities +{ + public sealed class Control + { } +} diff --git a/Core/Stateflows/Activities/Tokens/ControlToken.cs b/Core/Stateflows/Activities/Tokens/ControlToken.cs deleted file mode 100644 index 98f3f48d..00000000 --- a/Core/Stateflows/Activities/Tokens/ControlToken.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Stateflows.Common; - -namespace Stateflows.Activities -{ -#pragma warning disable S2094 // Classes should not be empty - public sealed class ControlToken : Token -#pragma warning restore S2094 // Classes should not be empty - { } -} diff --git a/Core/Stateflows/Activities/Tokens/EventToken.cs b/Core/Stateflows/Activities/Tokens/EventToken.cs deleted file mode 100644 index 94585ce7..00000000 --- a/Core/Stateflows/Activities/Tokens/EventToken.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Stateflows.Common; - -namespace Stateflows.Activities -{ - public class EventToken : Token - where TEvent : Event, new() - { - public TEvent Event { get; set; } - } -} diff --git a/Core/Stateflows/Activities/Tokens/ExceptionHolder.cs b/Core/Stateflows/Activities/Tokens/ExceptionHolder.cs new file mode 100644 index 00000000..a339d4c9 --- /dev/null +++ b/Core/Stateflows/Activities/Tokens/ExceptionHolder.cs @@ -0,0 +1,36 @@ +using System; +using Stateflows.Common.Extensions; + +namespace Stateflows.Activities +{ + public abstract class ExceptionHolder : TokenHolder + { + public Exception Exception { get; set; } + } + + public class ExceptionHolder : ExceptionHolder + where T : Exception + { + public ExceptionHolder() + { + Exception = default; + } + + public override string Name => name ??= typeof(T).GetReadableName(); + + public T TypedException + { + get => Exception as T; + set => Exception = value; + } + + protected override object GetBoxedPayload() + => Exception; + + public override bool Equals(object obj) + => obj is ExceptionHolder token && token.Id == Id; + + public override int GetHashCode() + => Id.GetHashCode(); + } +} diff --git a/Core/Stateflows/Activities/Tokens/ExceptionToken.cs b/Core/Stateflows/Activities/Tokens/ExceptionToken.cs deleted file mode 100644 index c52d96b5..00000000 --- a/Core/Stateflows/Activities/Tokens/ExceptionToken.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using Stateflows.Common; - -namespace Stateflows.Activities -{ - public sealed class ExceptionToken : Token - where TException : Exception - { - public TException Exception { get; set; } - } -} diff --git a/Core/Stateflows/Activities/Tokens/NodeReference.cs b/Core/Stateflows/Activities/Tokens/NodeReference.cs new file mode 100644 index 00000000..f6023a9a --- /dev/null +++ b/Core/Stateflows/Activities/Tokens/NodeReference.cs @@ -0,0 +1,9 @@ +using Stateflows.Activities.Models; + +namespace Stateflows.Activities +{ + internal sealed class NodeReference + { + public Node Node { get; set; } + } +} diff --git a/Core/Stateflows/Activities/Tokens/TokenHolder.cs b/Core/Stateflows/Activities/Tokens/TokenHolder.cs new file mode 100644 index 00000000..ffa05c35 --- /dev/null +++ b/Core/Stateflows/Activities/Tokens/TokenHolder.cs @@ -0,0 +1,41 @@ +using System; +using Newtonsoft.Json; +using Stateflows.Common; +using Stateflows.Common.Extensions; + +namespace Stateflows.Activities +{ + public abstract class TokenHolder + { + public Guid Id { get; set; } = Guid.NewGuid(); + + protected string name; + public virtual string Name => name ??= GetType().GetTokenName(); + + [JsonIgnore] + public object BoxedPayload { get; } + + protected abstract object GetBoxedPayload(); + } + + public class TokenHolder : TokenHolder + { + public TokenHolder() + { + Payload = default; + } + + public override string Name => name ??= typeof(T).GetReadableName(); + + public T Payload { get; set; } + + protected override object GetBoxedPayload() + => Payload; + + public override bool Equals(object obj) + => obj is TokenHolder token && token.Id == Id; + + public override int GetHashCode() + => Id.GetHashCode(); + } +} diff --git a/Core/Stateflows/Activities/Utils/IEnumerableExtensions.cs b/Core/Stateflows/Activities/Utils/IEnumerableExtensions.cs index fb875ef9..6e5ea1bc 100644 --- a/Core/Stateflows/Activities/Utils/IEnumerableExtensions.cs +++ b/Core/Stateflows/Activities/Utils/IEnumerableExtensions.cs @@ -1,31 +1,11 @@ -using System; -using System.Linq; +using System.Linq; using System.Collections.Generic; -using Stateflows.Common; -using Stateflows.Activities.Streams; +using Stateflows.Activities; namespace Stateflows.Utils { public static class IEnumerableExtensions { - public static IEnumerable Where(this IEnumerable source, Func predicate) - where TTarget : TSource - { - return source.Where(i => i is TTarget && predicate(i)) as IEnumerable; - } - - public static TTarget First(this IEnumerable source, Func predicate) - where TTarget : TSource - { - return (TTarget)source.First(i => i is TTarget && predicate(i)); - } - - public static TTarget First(this IEnumerable source) - where TTarget : TSource - { - return (TTarget)source.First(i => i is TTarget); - } - public static IEnumerable> Partition(this IEnumerable sequence, int size) { List partition = new List(size); @@ -45,7 +25,13 @@ public static IEnumerable> Partition(this IEnumerable seque } } - public static Token[] GetTokens(this IEnumerable streams) - => streams.SelectMany(stream => stream.Tokens).ToArray(); + internal static IEnumerable> ToTokens(this IEnumerable source) + => source.Select(t => new TokenHolder() { Payload = t }); + + internal static IEnumerable FromTokens(this IEnumerable> source) + => source.Select(t => t.Payload); + + internal static IEnumerable FromTokens(this IEnumerable source) + => source.Select(t => t.BoxedPayload); } } diff --git a/Core/Stateflows/Activities/Utils/ObjectExtensions.cs b/Core/Stateflows/Activities/Utils/ObjectExtensions.cs new file mode 100644 index 00000000..da42ad21 --- /dev/null +++ b/Core/Stateflows/Activities/Utils/ObjectExtensions.cs @@ -0,0 +1,34 @@ +using System; +using Stateflows.Activities; + +namespace Stateflows.Utils +{ + internal static class ObjectExtensions + { + internal static TokenHolder ToTokenHolder(this T payload) + => new TokenHolder() { Payload = payload }; + + internal static TokenHolder ToTokenHolder(this T payload, Type tokenType) + { + var holderType = typeof(TokenHolder<>).MakeGenericType(tokenType); + var holder = (TokenHolder)Activator.CreateInstance(holderType); + holderType.GetProperty("Payload").SetValue(holder, payload); + + return holder; + } + + internal static ExceptionHolder ToExceptionHolder(this T payload) + where T : Exception + => new ExceptionHolder() { Exception = payload }; + + internal static TokenHolder ToExceptionHolder(this T payload, Type exceptionType) + where T : Exception + { + var holderType = typeof(ExceptionHolder<>).MakeGenericType(exceptionType); + var holder = (ExceptionHolder)Activator.CreateInstance(holderType); + holderType.GetProperty("Exception").SetValue(holder, payload); + + return holder; + } + } +} diff --git a/Core/Stateflows/Common/Classes/BaseValueAccessor.cs b/Core/Stateflows/Common/Classes/BaseValueAccessor.cs new file mode 100644 index 00000000..a4790e7f --- /dev/null +++ b/Core/Stateflows/Common/Classes/BaseValueAccessor.cs @@ -0,0 +1,42 @@ +using System; +using System.Threading; +using Stateflows.Common.Interfaces; +using Stateflows.Common.Exceptions; + +namespace Stateflows.Common.Classes +{ + public static class ContextValuesHolder + { + public static readonly AsyncLocal GlobalValues = new AsyncLocal(); + public static readonly AsyncLocal StateValues = new AsyncLocal(); + public static readonly AsyncLocal SourceStateValues = new AsyncLocal(); + public static readonly AsyncLocal TargetStateValues = new AsyncLocal(); + } + + public class BaseValueAccessor + { + private readonly string valueName; + private readonly IContextValues valueSet; + + public BaseValueAccessor(string valueName, Func valueSetSelector, string collectionName) + { + this.valueName = valueName; + this.valueSet = valueSetSelector?.Invoke() ?? throw new StateflowsException($"{collectionName} set is not available in current context"); + } + + public void Set(T value) + => valueSet.Set(valueName, value); + + public bool IsSet + => valueSet.IsSet(valueName); + + public bool TryGet(out T value) + => valueSet.TryGet(valueName, out value); + + public T GetOrDefault(T defaultValue) + => valueSet.GetOrDefault(valueName, defaultValue); + + public void Remove() + => valueSet.Remove(valueName); + } +} diff --git a/Core/Stateflows/Common/Classes/ContextValues.cs b/Core/Stateflows/Common/Classes/ContextValues.cs index 203c2a97..13217be4 100644 --- a/Core/Stateflows/Common/Classes/ContextValues.cs +++ b/Core/Stateflows/Common/Classes/ContextValues.cs @@ -1,7 +1,7 @@ -using System.Collections.Generic; -using Newtonsoft.Json.Linq; -using Stateflows.Common.Utilities; +using Newtonsoft.Json.Linq; using Stateflows.Common.Interfaces; +using Stateflows.Common.Utilities; +using System.Collections.Generic; namespace Stateflows.Common.Classes { @@ -45,7 +45,9 @@ public bool TryGet(string key, out T value) var type = typeof(T); var deserializedData = type.IsPrimitive ? ParseStringToTypedValue(data) - : StateflowsJsonConverter.DeserializeObject(data); + : type.IsEnum + ? ParseStringToEnum(data) + : StateflowsJsonConverter.DeserializeObject(data); if (deserializedData is T t) { @@ -68,7 +70,9 @@ public T GetOrDefault(string key, T defaultValue) var type = typeof(T); var deserializedData = type.IsPrimitive ? ParseStringToTypedValue(data) - : StateflowsJsonConverter.DeserializeObject(data); + : type.IsEnum + ? ParseStringToEnum(data) + : StateflowsJsonConverter.DeserializeObject(data); if (deserializedData is T t) { @@ -96,6 +100,11 @@ public void Clear() } } + private static T ParseStringToEnum(string value) + { + return (T)(object)JToken.Parse(value).Value(); + } + private static T ParseStringToTypedValue(string value) { if (typeof(T) == typeof(string)) diff --git a/Core/Stateflows/Common/Classes/EventQueue.cs b/Core/Stateflows/Common/Classes/EventQueue.cs index 2cb04352..dd91508b 100644 --- a/Core/Stateflows/Common/Classes/EventQueue.cs +++ b/Core/Stateflows/Common/Classes/EventQueue.cs @@ -3,9 +3,11 @@ using System.Collections.Generic; using System.Threading.Tasks; using Stateflows.Common.Utilities; +using System.Runtime.Serialization; namespace Stateflows.Common.Classes { + [Serializable] public class EventQueue : LinkedList { private readonly object LockObject = new object(); @@ -17,6 +19,9 @@ public EventQueue(bool locked) Locked = locked; } + protected EventQueue(SerializationInfo info, StreamingContext context) : base(info, context) + { } + private readonly EventWaitHandle Event = new EventWaitHandle(false, EventResetMode.AutoReset); private readonly string QueueEmpty = "Queue empty."; diff --git a/Core/Stateflows/Common/Classes/GlobalValueAccessors.cs b/Core/Stateflows/Common/Classes/GlobalValueAccessors.cs new file mode 100644 index 00000000..eb724ae7 --- /dev/null +++ b/Core/Stateflows/Common/Classes/GlobalValueAccessors.cs @@ -0,0 +1,10 @@ +using Stateflows.Common.Classes; + +namespace Stateflows.Common +{ + public class GlobalValue : BaseValueAccessor + { + public GlobalValue(string valueName) : base(valueName, () => ContextValuesHolder.GlobalValues.Value, nameof(ContextValuesHolder.GlobalValues)) + { } + } +} diff --git a/Core/Stateflows/Common/Classes/ValueAccessors.cs b/Core/Stateflows/Common/Classes/ValueAccessors.cs new file mode 100644 index 00000000..aefd2c6d --- /dev/null +++ b/Core/Stateflows/Common/Classes/ValueAccessors.cs @@ -0,0 +1,22 @@ +using Stateflows.Common.Classes; + +namespace Stateflows.StateMachines +{ + public class StateValue : BaseValueAccessor + { + public StateValue(string valueName) : base(valueName, () => ContextValuesHolder.StateValues.Value, nameof(ContextValuesHolder.StateValues)) + { } + } + + public class SourceStateValue : BaseValueAccessor + { + public SourceStateValue(string valueName) : base(valueName, () => ContextValuesHolder.SourceStateValues.Value, nameof(ContextValuesHolder.SourceStateValues)) + { } + } + + public class TargetStateValue : BaseValueAccessor + { + public TargetStateValue(string valueName) : base(valueName, () => ContextValuesHolder.TargetStateValues.Value, nameof(ContextValuesHolder.TargetStateValues)) + { } + } +} diff --git a/Core/Stateflows/Common/Context/Interfaces/IBehaviorContext.cs b/Core/Stateflows/Common/Context/Interfaces/IBehaviorContext.cs index a79dbe9b..bfda57f4 100644 --- a/Core/Stateflows/Common/Context/Interfaces/IBehaviorContext.cs +++ b/Core/Stateflows/Common/Context/Interfaces/IBehaviorContext.cs @@ -1,17 +1,32 @@ -using System.Threading.Tasks; -using Stateflows.Common.Interfaces; +using Stateflows.Common.Interfaces; namespace Stateflows.Common.Context.Interfaces { public interface IBehaviorContext : ISubscriptions { + /// + /// Represents identifier of current behavior + /// BehaviorId Id { get; } + /// + /// Provides access to global context values of current behavior + /// IContextValues Values { get; } + /// + /// Sends an event to current behavior + /// + /// Type of an event + /// Event instance void Send(TEvent @event) where TEvent : Event, new(); + /// + /// Publishes a notification to all subscribers and watchers of current behavior + /// + /// Type of a notification + /// Notification instance void Publish(TNotification notification) where TNotification : Notification, new(); } diff --git a/Core/Stateflows/GlobalSuppressions.cs b/Core/Stateflows/GlobalSuppressions.cs new file mode 100644 index 00000000..2cfbe8f0 --- /dev/null +++ b/Core/Stateflows/GlobalSuppressions.cs @@ -0,0 +1,9 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("Major Code Smell", "S3246:Generic type parameters should be co/contravariant when possible", Justification = "", Scope = "type", Target = "~T:Stateflows.Activities.Registration.Interfaces.Base.IElseDecisionFlow`2")] +[assembly: SuppressMessage("Major Code Smell", "S3246:Generic type parameters should be co/contravariant when possible", Justification = "", Scope = "type", Target = "~T:Stateflows.Activities.Registration.Interfaces.Base.IDecisionFlow`2")] diff --git a/Core/Stateflows/StateMachines/Engine/Executor.cs b/Core/Stateflows/StateMachines/Engine/Executor.cs index d27afae1..7ecfd9f2 100644 --- a/Core/Stateflows/StateMachines/Engine/Executor.cs +++ b/Core/Stateflows/StateMachines/Engine/Executor.cs @@ -13,8 +13,7 @@ using Stateflows.StateMachines.Registration; using Stateflows.StateMachines.Context.Classes; using Stateflows.StateMachines.Context.Interfaces; -using Stateflows.Common.Initializer; -using Stateflows.Activities.Engine; +using Stateflows.Common.Classes; namespace Stateflows.StateMachines.Engine { @@ -540,6 +539,11 @@ public StateMachine GetStateMachine(Type stateMachineType, RootContext context) public TState GetState(IStateActionContext context) where TState : BaseState { + ContextValuesHolder.GlobalValues.Value = context.StateMachine.Values; + ContextValuesHolder.StateValues.Value = context.CurrentState.Values; + ContextValuesHolder.SourceStateValues.Value = null; + ContextValuesHolder.TargetStateValues.Value = null; + var state = ServiceProvider.GetService(); state.Context = context; @@ -550,6 +554,11 @@ public TTransition GetTransition(ITransitionContext where TTransition : Transition where TEvent : Event, new() { + ContextValuesHolder.GlobalValues.Value = context.StateMachine.Values; + ContextValuesHolder.StateValues.Value = null; + ContextValuesHolder.SourceStateValues.Value = context.SourceState.Values; + ContextValuesHolder.TargetStateValues.Value = context.TargetState?.Values; + var transition = ServiceProvider.GetService(); transition.Context = context; @@ -560,6 +569,11 @@ public TElseTransition GetElseTransition(ITransitionCon where TElseTransition : ElseTransition where TEvent : Event, new() { + ContextValuesHolder.GlobalValues.Value = context.StateMachine.Values; + ContextValuesHolder.StateValues.Value = null; + ContextValuesHolder.SourceStateValues.Value = context.SourceState.Values; + ContextValuesHolder.TargetStateValues.Value = context.TargetState?.Values; + var elseTransition = ServiceProvider.GetService(); elseTransition.Context = context; diff --git a/Core/Stateflows/StateMachines/Engine/Plugins/Behaviors.cs b/Core/Stateflows/StateMachines/Engine/Plugins/Behaviors.cs index dd27709b..d8df0edf 100644 --- a/Core/Stateflows/StateMachines/Engine/Plugins/Behaviors.cs +++ b/Core/Stateflows/StateMachines/Engine/Plugins/Behaviors.cs @@ -1,5 +1,4 @@ -using System; -using System.Linq; +using System.Linq; using System.Threading.Tasks; using Stateflows.Common; using Stateflows.StateMachines.Context.Classes; @@ -36,36 +35,6 @@ public Task AfterStateEntryAsync(IStateActionContext context) return Task.CompletedTask; } - public Task AfterStateExitAsync(IStateActionContext context) - => Task.CompletedTask; - - public Task AfterStateInitializeAsync(IStateActionContext context) - => Task.CompletedTask; - - public Task AfterStateFinalizeAsync(IStateActionContext context) - => Task.CompletedTask; - - public Task AfterStateMachineInitializeAsync(IStateMachineInitializationContext context) - => Task.CompletedTask; - - public Task AfterStateMachineFinalizeAsync(IStateMachineActionContext context) - => Task.CompletedTask; - - public Task AfterTransitionEffectAsync(ITransitionContext context) - => Task.CompletedTask; - - public Task AfterTransitionGuardAsync(IGuardContext context, bool guardResult) - => Task.CompletedTask; - - public Task BeforeProcessEventAsync(IEventContext context) - => Task.FromResult(true); - - public Task AfterProcessEventAsync(IEventContext context) - => Task.CompletedTask; - - public Task BeforeStateEntryAsync(IStateActionContext context) - => Task.CompletedTask; - public Task BeforeStateExitAsync(IStateActionContext context) { var vertex = (context as StateActionContext).Vertex; @@ -91,53 +60,5 @@ public Task BeforeStateExitAsync(IStateActionContext context) return Task.CompletedTask; } - - public Task BeforeStateInitializeAsync(IStateActionContext context) - => Task.CompletedTask; - - public Task BeforeStateFinalizeAsync(IStateActionContext context) - => Task.CompletedTask; - - public Task BeforeStateMachineInitializeAsync(IStateMachineInitializationContext context) - => Task.CompletedTask; - - public Task BeforeStateMachineFinalizeAsync(IStateMachineActionContext context) - => Task.CompletedTask; - - public Task BeforeTransitionEffectAsync(ITransitionContext context) - => Task.CompletedTask; - - public Task BeforeTransitionGuardAsync(IGuardContext context) - => Task.CompletedTask; - - public Task AfterHydrateAsync(IStateMachineActionContext context) - => Task.CompletedTask; - - public Task BeforeDehydrateAsync(IStateMachineActionContext context) - => Task.CompletedTask; - - public Task OnStateMachineInitializationExceptionAsync(IStateMachineInitializationContext context, Exception exception) - => Task.CompletedTask; - - public Task OnStateMachineFinalizationExceptionAsync(IStateMachineActionContext context, Exception exception) - => Task.CompletedTask; - - public Task OnTransitionGuardExceptionAsync(IGuardContext context, Exception exception) - => Task.CompletedTask; - - public Task OnTransitionEffectExceptionAsync(ITransitionContext context, Exception exception) - => Task.CompletedTask; - - public Task OnStateInitializationExceptionAsync(IStateActionContext context, Exception exception) - => Task.CompletedTask; - - public Task OnStateFinalizationExceptionAsync(IStateActionContext context, Exception exception) - => Task.CompletedTask; - - public Task OnStateEntryExceptionAsync(IStateActionContext context, Exception exception) - => Task.CompletedTask; - - public Task OnStateExitExceptionAsync(IStateActionContext context, Exception exception) - => Task.CompletedTask; } } diff --git a/Core/Stateflows/StateMachines/Engine/Plugins/ContextCleanup.cs b/Core/Stateflows/StateMachines/Engine/Plugins/ContextCleanup.cs index 5d2b294c..f289737d 100644 --- a/Core/Stateflows/StateMachines/Engine/Plugins/ContextCleanup.cs +++ b/Core/Stateflows/StateMachines/Engine/Plugins/ContextCleanup.cs @@ -25,18 +25,6 @@ public Task AfterStateExitAsync(IStateActionContext context) return Task.CompletedTask; } - public Task AfterStateInitializeAsync(IStateActionContext context) - => Task.CompletedTask; - - public Task AfterStateFinalizeAsync(IStateActionContext context) - => Task.CompletedTask; - - public Task AfterStateMachineInitializeAsync(IStateMachineInitializationContext context) - => Task.CompletedTask; - - public Task AfterStateMachineFinalizeAsync(IStateMachineActionContext context) - => Task.CompletedTask; - public Task AfterTransitionEffectAsync(ITransitionContext context) { if (context.TargetState != null) @@ -54,68 +42,5 @@ public Task AfterTransitionEffectAsync(ITransitionContext context) return Task.CompletedTask; } - - public Task AfterTransitionGuardAsync(IGuardContext context, bool guardResult) - => Task.CompletedTask; - - public Task BeforeProcessEventAsync(IEventContext context) - => Task.FromResult(true); - - public Task AfterProcessEventAsync(IEventContext context) - => Task.CompletedTask; - - public Task BeforeStateEntryAsync(IStateActionContext context) - => Task.CompletedTask; - - public Task BeforeStateExitAsync(IStateActionContext context) - => Task.CompletedTask; - - public Task BeforeStateInitializeAsync(IStateActionContext context) - => Task.CompletedTask; - - public Task BeforeStateFinalizeAsync(IStateActionContext context) - => Task.CompletedTask; - - public Task BeforeStateMachineInitializeAsync(IStateMachineInitializationContext context) - => Task.CompletedTask; - - public Task BeforeStateMachineFinalizeAsync(IStateMachineActionContext context) - => Task.CompletedTask; - - public Task BeforeTransitionEffectAsync(ITransitionContext context) - => Task.CompletedTask; - - public Task BeforeTransitionGuardAsync(IGuardContext context) - => Task.CompletedTask; - - public Task AfterHydrateAsync(IStateMachineActionContext context) - => Task.CompletedTask; - - public Task BeforeDehydrateAsync(IStateMachineActionContext context) - => Task.CompletedTask; - - public Task OnStateMachineInitializationExceptionAsync(IStateMachineInitializationContext context, Exception exception) - => Task.CompletedTask; - - public Task OnStateMachineFinalizationExceptionAsync(IStateMachineActionContext context, Exception exception) - => Task.CompletedTask; - - public Task OnTransitionGuardExceptionAsync(IGuardContext context, Exception exception) - => Task.CompletedTask; - - public Task OnTransitionEffectExceptionAsync(ITransitionContext context, Exception exception) - => Task.CompletedTask; - - public Task OnStateInitializationExceptionAsync(IStateActionContext context, Exception exception) - => Task.CompletedTask; - - public Task OnStateFinalizationExceptionAsync(IStateActionContext context, Exception exception) - => Task.CompletedTask; - - public Task OnStateEntryExceptionAsync(IStateActionContext context, Exception exception) - => Task.CompletedTask; - - public Task OnStateExitExceptionAsync(IStateActionContext context, Exception exception) - => Task.CompletedTask; } } diff --git a/Core/Stateflows/StateMachines/Engine/Plugins/Notifications.cs b/Core/Stateflows/StateMachines/Engine/Plugins/Notifications.cs index 01409d9d..13927c47 100644 --- a/Core/Stateflows/StateMachines/Engine/Plugins/Notifications.cs +++ b/Core/Stateflows/StateMachines/Engine/Plugins/Notifications.cs @@ -11,19 +11,37 @@ namespace Stateflows.StateMachines.Engine internal class Notifications : IStateMachinePlugin { public Task AfterStateEntryAsync(IStateActionContext context) - => Task.CompletedTask; + { + Trace.WriteLine($"⦗→s⦘ State Machine '{context.StateMachine.Id.Name}': entered state '{context.CurrentState.Name}'"); + + return Task.CompletedTask; + } public Task AfterStateExitAsync(IStateActionContext context) - => Task.CompletedTask; + { + Trace.WriteLine($"⦗→s⦘ State Machine '{context.StateMachine.Id.Name}': exited state '{context.CurrentState.Name}'"); + + return Task.CompletedTask; + } public Task AfterStateInitializeAsync(IStateActionContext context) - => Task.CompletedTask; + { + Trace.WriteLine($"⦗→s⦘ State Machine '{context.StateMachine.Id.Name}': initialized state '{context.CurrentState.Name}'"); + + return Task.CompletedTask; + } public Task AfterStateFinalizeAsync(IStateActionContext context) - => Task.CompletedTask; + { + Trace.WriteLine($"⦗→s⦘ State Machine '{context.StateMachine.Id.Name}': finalized state '{context.CurrentState.Name}'"); + + return Task.CompletedTask; + } public Task AfterStateMachineInitializeAsync(IStateMachineInitializationContext context) { + Trace.WriteLine($"⦗→s⦘ State Machine '{context.StateMachine.Id.Name}': initialized"); + var executor = context.StateMachine.GetExecutor(); var notification = new BehaviorStatusNotification() { @@ -38,6 +56,8 @@ public Task AfterStateMachineInitializeAsync(IStateMachineInitializationContext public Task AfterStateMachineFinalizeAsync(IStateMachineActionContext context) { + Trace.WriteLine($"⦗→s⦘ State Machine '{context.StateMachine.Id.Name}': finalized"); + var notification = new BehaviorStatusNotification() { BehaviorStatus = BehaviorStatus.Finalized }; context.StateMachine.Publish(notification); @@ -49,13 +69,44 @@ public Task AfterTransitionEffectAsync(ITransitionContext context) => Task.CompletedTask; public Task AfterTransitionGuardAsync(IGuardContext context, bool guardResult) - => Task.CompletedTask; + { + if (guardResult) + { + if (context.TargetState != null) + { + Trace.WriteLine($"⦗→s⦘ State Machine '{context.StateMachine.Id.Name}': event '{context.Event.Name}' triggered transition from state '{context.SourceState.Name}' to state '{context.TargetState.Name}'"); + } + else + { + Trace.WriteLine($"⦗→s⦘ State Machine '{context.StateMachine.Id.Name}': event '{context.Event.Name}' triggered reaction in state '{context.SourceState.Name}'"); + } + } + else + { + if (context.TargetState != null) + { + Trace.WriteLine($"⦗→s⦘ State Machine '{context.StateMachine.Id.Name}': guard stopped event '{context.Event.Name}' from triggering transition from state '{context.SourceState.Name}' to state '{context.TargetState.Name}'"); + } + else + { + Trace.WriteLine($"⦗→s⦘ State Machine '{context.StateMachine.Id.Name}': guard stopped event '{context.Event.Name}' from triggering reaction in state '{context.SourceState.Name}'"); + } + } + + return Task.CompletedTask; + } public Task BeforeProcessEventAsync(IEventContext context) - => Task.FromResult(true); + { + Trace.WriteLine($"⦗→s⦘ State Machine '{context.StateMachine.Id.Name}': received event '{context.Event.Name}', trying to process it"); + + return Task.FromResult(true); + } public Task AfterProcessEventAsync(IEventContext context) { + Trace.WriteLine($"⦗→s⦘ State Machine '{context.StateMachine.Id.Name}': processed event '{context.Event.Name}'"); + var executor = context.StateMachine.GetExecutor(); if (executor.StateHasChanged) { @@ -67,65 +118,9 @@ public Task AfterProcessEventAsync(IEventContext context) }; context.StateMachine.Publish(notification); - - Debug.WriteLine($"--> current state notification published {DateTime.Now}"); } return Task.CompletedTask; } - - public Task BeforeStateEntryAsync(IStateActionContext context) - => Task.CompletedTask; - - public Task BeforeStateExitAsync(IStateActionContext context) - => Task.CompletedTask; - - public Task BeforeStateInitializeAsync(IStateActionContext context) - => Task.CompletedTask; - - public Task BeforeStateFinalizeAsync(IStateActionContext context) - => Task.CompletedTask; - - public Task BeforeStateMachineInitializeAsync(IStateMachineInitializationContext context) - => Task.CompletedTask; - - public Task BeforeStateMachineFinalizeAsync(IStateMachineActionContext context) - => Task.CompletedTask; - - public Task BeforeTransitionEffectAsync(ITransitionContext context) - => Task.CompletedTask; - - public Task BeforeTransitionGuardAsync(IGuardContext context) - => Task.CompletedTask; - - public Task AfterHydrateAsync(IStateMachineActionContext context) - => Task.CompletedTask; - - public Task BeforeDehydrateAsync(IStateMachineActionContext context) - => Task.CompletedTask; - - public Task OnStateMachineInitializationExceptionAsync(IStateMachineInitializationContext context, Exception exception) - => Task.CompletedTask; - - public Task OnStateMachineFinalizationExceptionAsync(IStateMachineActionContext context, Exception exception) - => Task.CompletedTask; - - public Task OnTransitionGuardExceptionAsync(IGuardContext context, Exception exception) - => Task.CompletedTask; - - public Task OnTransitionEffectExceptionAsync(ITransitionContext context, Exception exception) - => Task.CompletedTask; - - public Task OnStateInitializationExceptionAsync(IStateActionContext context, Exception exception) - => Task.CompletedTask; - - public Task OnStateFinalizationExceptionAsync(IStateActionContext context, Exception exception) - => Task.CompletedTask; - - public Task OnStateEntryExceptionAsync(IStateActionContext context, Exception exception) - => Task.CompletedTask; - - public Task OnStateExitExceptionAsync(IStateActionContext context, Exception exception) - => Task.CompletedTask; } } diff --git a/Core/Stateflows/StateMachines/Engine/Plugins/TimeEvents.cs b/Core/Stateflows/StateMachines/Engine/Plugins/TimeEvents.cs index 9daba42e..be03cfaf 100644 --- a/Core/Stateflows/StateMachines/Engine/Plugins/TimeEvents.cs +++ b/Core/Stateflows/StateMachines/Engine/Plugins/TimeEvents.cs @@ -37,24 +37,6 @@ public Task AfterStateExitAsync(IStateActionContext context) return Task.CompletedTask; } - public Task AfterStateInitializeAsync(IStateActionContext context) - => Task.CompletedTask; - - public Task AfterStateFinalizeAsync(IStateActionContext context) - => Task.CompletedTask; - - public Task AfterStateMachineInitializeAsync(IStateMachineInitializationContext context) - => Task.CompletedTask; - - public Task AfterStateMachineFinalizeAsync(IStateMachineActionContext context) - => Task.CompletedTask; - - public Task AfterTransitionEffectAsync(ITransitionContext context) - => Task.CompletedTask; - - public Task AfterTransitionGuardAsync(IGuardContext context, bool guardResult) - => Task.CompletedTask; - public Task BeforeProcessEventAsync(IEventContext context) { var result = true; @@ -122,27 +104,6 @@ public Task AfterProcessEventAsync(IEventContext context) return Task.CompletedTask; } - public Task BeforeStateEntryAsync(IStateActionContext context) - => Task.CompletedTask; - - public Task BeforeStateExitAsync(IStateActionContext context) - => Task.CompletedTask; - - public Task BeforeStateInitializeAsync(IStateActionContext context) - => Task.CompletedTask; - - public Task BeforeStateFinalizeAsync(IStateActionContext context) - => Task.CompletedTask; - - public Task BeforeStateMachineInitializeAsync(IStateMachineInitializationContext context) - => Task.CompletedTask; - - public Task BeforeStateMachineFinalizeAsync(IStateMachineActionContext context) - => Task.CompletedTask; - - public Task BeforeTransitionEffectAsync(ITransitionContext context) - => Task.CompletedTask; - public Task BeforeTransitionGuardAsync(IGuardContext context) { if (ConsumedInTransition == null && (context as IEdgeContext).Edge.Trigger == context.ExecutionTrigger.Name) @@ -217,29 +178,5 @@ public bool Equals(Edge x, Edge y) public int GetHashCode(Edge obj) => obj.Identifier.GetHashCode(); - - public Task OnStateMachineInitializationExceptionAsync(IStateMachineInitializationContext context, Exception exception) - => Task.CompletedTask; - - public Task OnStateMachineFinalizationExceptionAsync(IStateMachineActionContext context, Exception exception) - => Task.CompletedTask; - - public Task OnTransitionGuardExceptionAsync(IGuardContext context, Exception exception) - => Task.CompletedTask; - - public Task OnTransitionEffectExceptionAsync(ITransitionContext context, Exception exception) - => Task.CompletedTask; - - public Task OnStateInitializationExceptionAsync(IStateActionContext context, Exception exception) - => Task.CompletedTask; - - public Task OnStateFinalizationExceptionAsync(IStateActionContext context, Exception exception) - => Task.CompletedTask; - - public Task OnStateEntryExceptionAsync(IStateActionContext context, Exception exception) - => Task.CompletedTask; - - public Task OnStateExitExceptionAsync(IStateActionContext context, Exception exception) - => Task.CompletedTask; } } diff --git a/Core/Stateflows/StateMachines/Engine/Provider.cs b/Core/Stateflows/StateMachines/Engine/Provider.cs index 65423cf9..e452f501 100644 --- a/Core/Stateflows/StateMachines/Engine/Provider.cs +++ b/Core/Stateflows/StateMachines/Engine/Provider.cs @@ -26,9 +26,7 @@ public Provider(StateMachinesRegister register, StateflowsEngine engine, IServic ServiceProvider = serviceProvider; } -#pragma warning disable CS0067 // The event 'Provider.BehaviorClassesChanged' is never used public event ActionAsync BehaviorClassesChanged; -#pragma warning restore CS0067 // The event 'Provider.BehaviorClassesChanged' is never used public bool TryProvideBehavior(BehaviorId id, out IBehavior behavior) { diff --git a/Core/Stateflows/StateMachines/Interfaces/IStateMachineExceptionHandler.cs b/Core/Stateflows/StateMachines/Interfaces/IStateMachineExceptionHandler.cs index 4f45fa4c..d3ca00ee 100644 --- a/Core/Stateflows/StateMachines/Interfaces/IStateMachineExceptionHandler.cs +++ b/Core/Stateflows/StateMachines/Interfaces/IStateMachineExceptionHandler.cs @@ -7,13 +7,28 @@ namespace Stateflows.StateMachines { public interface IStateMachineExceptionHandler { - Task OnStateMachineInitializationExceptionAsync(IStateMachineInitializationContext context, Exception exception); - Task OnStateMachineFinalizationExceptionAsync(IStateMachineActionContext context, Exception exception); - Task OnTransitionGuardExceptionAsync(IGuardContext context, Exception exception); - Task OnTransitionEffectExceptionAsync(ITransitionContext context, Exception exception); - Task OnStateInitializationExceptionAsync(IStateActionContext context, Exception exception); - Task OnStateFinalizationExceptionAsync(IStateActionContext context, Exception exception); - Task OnStateEntryExceptionAsync(IStateActionContext context, Exception exception); - Task OnStateExitExceptionAsync(IStateActionContext context, Exception exception); + Task OnStateMachineInitializationExceptionAsync(IStateMachineInitializationContext context, Exception exception) + => Task.CompletedTask; + + Task OnStateMachineFinalizationExceptionAsync(IStateMachineActionContext context, Exception exception) + => Task.CompletedTask; + + Task OnTransitionGuardExceptionAsync(IGuardContext context, Exception exception) + => Task.CompletedTask; + + Task OnTransitionEffectExceptionAsync(ITransitionContext context, Exception exception) + => Task.CompletedTask; + + Task OnStateInitializationExceptionAsync(IStateActionContext context, Exception exception) + => Task.CompletedTask; + + Task OnStateFinalizationExceptionAsync(IStateActionContext context, Exception exception) + => Task.CompletedTask; + + Task OnStateEntryExceptionAsync(IStateActionContext context, Exception exception) + => Task.CompletedTask; + + Task OnStateExitExceptionAsync(IStateActionContext context, Exception exception) + => Task.CompletedTask; } } diff --git a/Core/Stateflows/StateMachines/Interfaces/IStateMachineInterceptor.cs b/Core/Stateflows/StateMachines/Interfaces/IStateMachineInterceptor.cs index f406e0df..04d56da3 100644 --- a/Core/Stateflows/StateMachines/Interfaces/IStateMachineInterceptor.cs +++ b/Core/Stateflows/StateMachines/Interfaces/IStateMachineInterceptor.cs @@ -6,9 +6,16 @@ namespace Stateflows.StateMachines { public interface IStateMachineInterceptor { - Task AfterHydrateAsync(IStateMachineActionContext context); - Task BeforeDehydrateAsync(IStateMachineActionContext context); - Task BeforeProcessEventAsync(IEventContext context); - Task AfterProcessEventAsync(IEventContext context); + Task AfterHydrateAsync(IStateMachineActionContext context) + => Task.CompletedTask; + + Task BeforeDehydrateAsync(IStateMachineActionContext context) + => Task.CompletedTask; + + Task BeforeProcessEventAsync(IEventContext context) + => Task.FromResult(true); + + Task AfterProcessEventAsync(IEventContext context) + => Task.CompletedTask; } } diff --git a/Core/Stateflows/StateMachines/Interfaces/IStateMachineObserver.cs b/Core/Stateflows/StateMachines/Interfaces/IStateMachineObserver.cs index b91feef3..ebc9aa6c 100644 --- a/Core/Stateflows/StateMachines/Interfaces/IStateMachineObserver.cs +++ b/Core/Stateflows/StateMachines/Interfaces/IStateMachineObserver.cs @@ -6,21 +6,52 @@ namespace Stateflows.StateMachines { public interface IStateMachineObserver { - Task BeforeStateMachineInitializeAsync(IStateMachineInitializationContext context); - Task AfterStateMachineInitializeAsync(IStateMachineInitializationContext context); - Task BeforeStateMachineFinalizeAsync(IStateMachineActionContext context); - Task AfterStateMachineFinalizeAsync(IStateMachineActionContext context); - Task BeforeStateInitializeAsync(IStateActionContext context); - Task AfterStateInitializeAsync(IStateActionContext context); - Task BeforeStateFinalizeAsync(IStateActionContext context); - Task AfterStateFinalizeAsync(IStateActionContext context); - Task BeforeStateEntryAsync(IStateActionContext context); - Task AfterStateEntryAsync(IStateActionContext context); - Task BeforeStateExitAsync(IStateActionContext context); - Task AfterStateExitAsync(IStateActionContext context); - Task BeforeTransitionGuardAsync(IGuardContext context); - Task AfterTransitionGuardAsync(IGuardContext context, bool guardResult); - Task BeforeTransitionEffectAsync(ITransitionContext context); - Task AfterTransitionEffectAsync(ITransitionContext context); + Task BeforeStateMachineInitializeAsync(IStateMachineInitializationContext context) + => Task.CompletedTask; + + Task AfterStateMachineInitializeAsync(IStateMachineInitializationContext context) + => Task.CompletedTask; + + Task BeforeStateMachineFinalizeAsync(IStateMachineActionContext context) + => Task.CompletedTask; + + Task AfterStateMachineFinalizeAsync(IStateMachineActionContext context) + => Task.CompletedTask; + + Task BeforeStateInitializeAsync(IStateActionContext context) + => Task.CompletedTask; + + Task AfterStateInitializeAsync(IStateActionContext context) + => Task.CompletedTask; + + Task BeforeStateFinalizeAsync(IStateActionContext context) + => Task.CompletedTask; + + Task AfterStateFinalizeAsync(IStateActionContext context) + => Task.CompletedTask; + + Task BeforeStateEntryAsync(IStateActionContext context) + => Task.CompletedTask; + + Task AfterStateEntryAsync(IStateActionContext context) + => Task.CompletedTask; + + Task BeforeStateExitAsync(IStateActionContext context) + => Task.CompletedTask; + + Task AfterStateExitAsync(IStateActionContext context) + => Task.CompletedTask; + + Task BeforeTransitionGuardAsync(IGuardContext context) + => Task.CompletedTask; + + Task AfterTransitionGuardAsync(IGuardContext context, bool guardResult) + => Task.CompletedTask; + + Task BeforeTransitionEffectAsync(ITransitionContext context) + => Task.CompletedTask; + + Task AfterTransitionEffectAsync(ITransitionContext context) + => Task.CompletedTask; } } diff --git a/Core/Stateflows/StateMachines/Models/Graph.cs b/Core/Stateflows/StateMachines/Models/Graph.cs index f3ef11c6..be33317e 100644 --- a/Core/Stateflows/StateMachines/Models/Graph.cs +++ b/Core/Stateflows/StateMachines/Models/Graph.cs @@ -97,20 +97,6 @@ public void Build() { throw new TransitionDefinitionException($"Transition target state '{edge.TargetName}' is not registered", Class); } - - //var vertices = edge.Source.Parent?.Vertices ?? Vertices; - //if (vertices.TryGetValue(edge.TargetName, out var target)) - //{ - // edge.Target = target; - //} - //else - //{ - // throw new TransitionDefinitionException(edge.Source.Parent is null - // ? $"Transition target state '{edge.TargetName}' is not registered in root level of state machine '{Name}'" - // : $"Transition target state '{edge.TargetName}' is not defined on the same level as transition source '{edge.SourceName}' in state machine '{Name}'", - // Class - // ); - //} } if (edge.IsElse) @@ -118,8 +104,6 @@ public void Build() var siblings = edge.Source.Edges.Values.Any(e => !e.IsElse && e.Trigger == edge.Trigger - //&& - //e.Type == edge.Type ); if (!siblings) diff --git a/Core/Stateflows/StateMachines/Registration/Builders/StateBuilder.cs b/Core/Stateflows/StateMachines/Registration/Builders/StateBuilder.cs index 4b5d74f2..1bd1d4b3 100644 --- a/Core/Stateflows/StateMachines/Registration/Builders/StateBuilder.cs +++ b/Core/Stateflows/StateMachines/Registration/Builders/StateBuilder.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Stateflows.Common; +using Stateflows.Common.Exceptions; using Stateflows.Common.Registration; using Stateflows.StateMachines.Events; using Stateflows.StateMachines.Models; @@ -56,7 +57,14 @@ public IStateBuilder AddOnInitialize(Func actionAsync } catch (Exception e) { - await c.Executor.Inspector.OnStateInitializeExceptionAsync(context, e); + if (e is StateflowsException) + { + throw; + } + else + { + await c.Executor.Inspector.OnStateInitializeExceptionAsync(context, e); + } } } ); @@ -80,7 +88,14 @@ public IStateBuilder AddOnFinalize(Func actionAsync) } catch (Exception e) { - await c.Executor.Inspector.OnStateFinalizeExceptionAsync(context, e); + if (e is StateflowsException) + { + throw; + } + else + { + await c.Executor.Inspector.OnStateFinalizeExceptionAsync(context, e); + } } } ); @@ -104,7 +119,14 @@ public IStateBuilder AddOnEntry(Func actionAsync) } catch (Exception e) { - await c.Executor.Inspector.OnStateEntryExceptionAsync(context, e); + if (e is StateflowsException) + { + throw; + } + else + { + await c.Executor.Inspector.OnStateEntryExceptionAsync(context, e); + } } } ); @@ -128,7 +150,14 @@ public IStateBuilder AddOnExit(Func actionAsync) } catch (Exception e) { - await c.Executor.Inspector.OnStateExitExceptionAsync(context, e); + if (e is StateflowsException) + { + throw; + } + else + { + await c.Executor.Inspector.OnStateExitExceptionAsync(context, e); + } } } ); diff --git a/Core/Stateflows/StateMachines/Registration/Builders/StateMachineBuilder.cs b/Core/Stateflows/StateMachines/Registration/Builders/StateMachineBuilder.cs index de3d755a..5b12fea3 100644 --- a/Core/Stateflows/StateMachines/Registration/Builders/StateMachineBuilder.cs +++ b/Core/Stateflows/StateMachines/Registration/Builders/StateMachineBuilder.cs @@ -209,12 +209,21 @@ public IInitializedStateMachineBuilder AddObserver(StateMachineObserverFactory o return this; } + IStateMachineBuilder IStateMachineUtils.AddInterceptor(StateMachineInterceptorFactory interceptorFactory) + => AddInterceptor(interceptorFactory) as IStateMachineBuilder; + IStateMachineBuilder IStateMachineUtils.AddInterceptor() => AddInterceptor() as IStateMachineBuilder; + IStateMachineBuilder IStateMachineUtils.AddObserver(StateMachineObserverFactory observerFactory) + => AddObserver(observerFactory) as IStateMachineBuilder; + IStateMachineBuilder IStateMachineUtils.AddObserver() => AddObserver() as IStateMachineBuilder; + IStateMachineBuilder IStateMachineUtils.AddExceptionHandler(StateMachineExceptionHandlerFactory exceptionHandlerFactory) + => AddExceptionHandler(exceptionHandlerFactory) as IStateMachineBuilder; + IStateMachineBuilder IStateMachineUtils.AddExceptionHandler() => AddExceptionHandler() as IStateMachineBuilder; @@ -227,12 +236,21 @@ IStateMachineBuilder IStateMachineEvents.AddOnInitialize.AddOnFinalize(Func actionAsync) => AddOnFinalize(actionAsync) as IStateMachineBuilder; + IFinalizedStateMachineBuilder IStateMachineUtils.AddInterceptor(StateMachineInterceptorFactory interceptorFactory) + => AddInterceptor(interceptorFactory) as IFinalizedStateMachineBuilder; + IFinalizedStateMachineBuilder IStateMachineUtils.AddInterceptor() => AddInterceptor() as IFinalizedStateMachineBuilder; + IFinalizedStateMachineBuilder IStateMachineUtils.AddObserver(StateMachineObserverFactory observerFactory) + => AddObserver(observerFactory) as IFinalizedStateMachineBuilder; + IFinalizedStateMachineBuilder IStateMachineUtils.AddObserver() => AddObserver() as IFinalizedStateMachineBuilder; + IFinalizedStateMachineBuilder IStateMachineUtils.AddExceptionHandler(StateMachineExceptionHandlerFactory exceptionHandlerFactory) + => AddExceptionHandler(exceptionHandlerFactory) as IFinalizedStateMachineBuilder; + IFinalizedStateMachineBuilder IStateMachineUtils.AddExceptionHandler() => AddExceptionHandler() as IFinalizedStateMachineBuilder; @@ -255,12 +273,21 @@ ITypedFinalizedStateMachineBuilder IStateMachineFinal.AddCompositeState(string stateName, CompositeStateBuildAction compositeStateBuildAction) => AddCompositeState(stateName, compositeStateBuildAction) as ITypedInitializedStateMachineBuilder; + ITypedInitializedStateMachineBuilder IStateMachineUtils.AddInterceptor(StateMachineInterceptorFactory interceptorFactory) + => AddInterceptor(interceptorFactory) as ITypedInitializedStateMachineBuilder; + ITypedInitializedStateMachineBuilder IStateMachineUtils.AddInterceptor() => AddInterceptor() as ITypedInitializedStateMachineBuilder; + ITypedInitializedStateMachineBuilder IStateMachineUtils.AddObserver(StateMachineObserverFactory observerFactory) + => AddObserver(observerFactory) as ITypedInitializedStateMachineBuilder; + ITypedInitializedStateMachineBuilder IStateMachineUtils.AddObserver() => AddObserver() as ITypedInitializedStateMachineBuilder; + ITypedInitializedStateMachineBuilder IStateMachineUtils.AddExceptionHandler(StateMachineExceptionHandlerFactory exceptionHandlerFactory) + => AddExceptionHandler(exceptionHandlerFactory) as ITypedInitializedStateMachineBuilder; + ITypedInitializedStateMachineBuilder IStateMachineUtils.AddExceptionHandler() => AddExceptionHandler() as ITypedInitializedStateMachineBuilder; @@ -270,21 +297,39 @@ ITypedInitializedStateMachineBuilder IStateMachineInitial.AddInitialCompositeState(string stateName, CompositeStateBuildAction compositeStateBuildAction) => AddInitialCompositeState(stateName, compositeStateBuildAction) as ITypedInitializedStateMachineBuilder; + ITypedStateMachineBuilder IStateMachineUtils.AddInterceptor(StateMachineInterceptorFactory interceptorFactory) + => AddInterceptor(interceptorFactory) as ITypedStateMachineBuilder; + ITypedStateMachineBuilder IStateMachineUtils.AddInterceptor() => AddInterceptor() as ITypedStateMachineBuilder; + ITypedStateMachineBuilder IStateMachineUtils.AddObserver(StateMachineObserverFactory observerFactory) + => AddObserver(observerFactory) as ITypedStateMachineBuilder; + ITypedStateMachineBuilder IStateMachineUtils.AddObserver() => AddObserver() as ITypedStateMachineBuilder; ITypedStateMachineBuilder IStateMachineUtils.AddExceptionHandler() => AddExceptionHandler() as ITypedStateMachineBuilder; + ITypedStateMachineBuilder IStateMachineUtils.AddExceptionHandler(StateMachineExceptionHandlerFactory exceptionHandlerFactory) + => AddExceptionHandler(exceptionHandlerFactory) as ITypedStateMachineBuilder; + + ITypedFinalizedStateMachineBuilder IStateMachineUtils.AddInterceptor(StateMachineInterceptorFactory interceptorFactory) + => AddInterceptor(interceptorFactory) as ITypedFinalizedStateMachineBuilder; + ITypedFinalizedStateMachineBuilder IStateMachineUtils.AddInterceptor() => AddInterceptor() as ITypedFinalizedStateMachineBuilder; + ITypedFinalizedStateMachineBuilder IStateMachineUtils.AddObserver(StateMachineObserverFactory observerFactory) + => AddObserver(observerFactory) as ITypedFinalizedStateMachineBuilder; + ITypedFinalizedStateMachineBuilder IStateMachineUtils.AddObserver() => AddObserver() as ITypedFinalizedStateMachineBuilder; + ITypedFinalizedStateMachineBuilder IStateMachineUtils.AddExceptionHandler(StateMachineExceptionHandlerFactory exceptionHandlerFactory) + => AddExceptionHandler(exceptionHandlerFactory) as ITypedFinalizedStateMachineBuilder; + ITypedFinalizedStateMachineBuilder IStateMachineUtils.AddExceptionHandler() => AddExceptionHandler() as ITypedFinalizedStateMachineBuilder; #endregion diff --git a/Core/Stateflows/StateMachines/Registration/Builders/TransitionBuilder.cs b/Core/Stateflows/StateMachines/Registration/Builders/TransitionBuilder.cs index 53e7ea49..5e505b74 100644 --- a/Core/Stateflows/StateMachines/Registration/Builders/TransitionBuilder.cs +++ b/Core/Stateflows/StateMachines/Registration/Builders/TransitionBuilder.cs @@ -9,6 +9,7 @@ using Stateflows.StateMachines.Registration.Extensions; using Stateflows.StateMachines.Registration.Interfaces.Base; using Stateflows.StateMachines.Events; +using Stateflows.Common.Exceptions; namespace Stateflows.StateMachines.Registration.Builders { @@ -50,7 +51,14 @@ public ITransitionBuilder AddGuard(Func, Task AddEffect(Func, Tas } catch (Exception e) { - await c.Executor.Inspector.OnTransitionEffectExceptionAsync(context, e); + if (e is StateflowsException) + { + throw; + } + else + { + await c.Executor.Inspector.OnTransitionEffectExceptionAsync(context, e); + } } } ); diff --git a/Core/Stateflows/StateMachines/Registration/Interfaces/Base/IStateMachineUtils.cs b/Core/Stateflows/StateMachines/Registration/Interfaces/Base/IStateMachineUtils.cs index b35de741..2a60cf94 100644 --- a/Core/Stateflows/StateMachines/Registration/Interfaces/Base/IStateMachineUtils.cs +++ b/Core/Stateflows/StateMachines/Registration/Interfaces/Base/IStateMachineUtils.cs @@ -2,12 +2,18 @@ { public interface IStateMachineUtils { + TReturn AddInterceptor(StateMachineInterceptorFactory interceptorFactory); + TReturn AddInterceptor() where TInterceptor : class, IStateMachineInterceptor; + TReturn AddObserver(StateMachineObserverFactory observerFactory); + TReturn AddObserver() where TObserver : class, IStateMachineObserver; + TReturn AddExceptionHandler(StateMachineExceptionHandlerFactory exceptionHandlerFactory); + TReturn AddExceptionHandler() where TExceptionHandler : class, IStateMachineExceptionHandler; } diff --git a/Core/Stateflows/StateMachines/Registration/Interfaces/Extensions/CompositeStateBuilder/StateMachine/InitializedCompositeStateBuilderTypedExtensions.cs b/Core/Stateflows/StateMachines/Registration/Interfaces/Extensions/CompositeStateBuilder/StateMachine/InitializedCompositeStateBuilderTypedExtensions.cs index 06201dcb..f648486c 100644 --- a/Core/Stateflows/StateMachines/Registration/Interfaces/Extensions/CompositeStateBuilder/StateMachine/InitializedCompositeStateBuilderTypedExtensions.cs +++ b/Core/Stateflows/StateMachines/Registration/Interfaces/Extensions/CompositeStateBuilder/StateMachine/InitializedCompositeStateBuilderTypedExtensions.cs @@ -9,9 +9,7 @@ public static class InitializedCompositeStateBuilderTypedExtensions { #region AddFinalState [DebuggerHidden] -#pragma warning disable S2326 // Unused type parameters should be removed public static IFinalizedCompositeStateBuilder AddState(this IInitializedCompositeStateBuilder builder, string stateName = FinalState.Name) -#pragma warning restore S2326 // Unused type parameters should be removed where TFinalState : FinalState => builder.AddFinalState(stateName); #endregion diff --git a/Core/Stateflows/StateMachines/Registration/Interfaces/Extensions/StateMachineBuilder/StateMachine/InitializedStateMachineBuilderTypedExtensions.cs b/Core/Stateflows/StateMachines/Registration/Interfaces/Extensions/StateMachineBuilder/StateMachine/InitializedStateMachineBuilderTypedExtensions.cs index 3a5c5581..588b661a 100644 --- a/Core/Stateflows/StateMachines/Registration/Interfaces/Extensions/StateMachineBuilder/StateMachine/InitializedStateMachineBuilderTypedExtensions.cs +++ b/Core/Stateflows/StateMachines/Registration/Interfaces/Extensions/StateMachineBuilder/StateMachine/InitializedStateMachineBuilderTypedExtensions.cs @@ -9,9 +9,7 @@ public static class InitializedStateMachineBuilderTypedExtensions { #region AddFinalState [DebuggerHidden] -#pragma warning disable S2326 // Unused type parameters should be removed public static IFinalizedStateMachineBuilder AddState(this IInitializedStateMachineBuilder builder, string stateName = FinalState.Name) -#pragma warning restore S2326 // Unused type parameters should be removed where TFinalState : FinalState => builder.AddFinalState(stateName); #endregion diff --git a/Core/Stateflows/StateMachines/Registration/Interfaces/Extensions/TypedCompositeStateBuilder/StateMachine/TypedInitializedCompositeStateBuilderTypedExtensions.cs b/Core/Stateflows/StateMachines/Registration/Interfaces/Extensions/TypedCompositeStateBuilder/StateMachine/TypedInitializedCompositeStateBuilderTypedExtensions.cs index fe9867ea..83ce62db 100644 --- a/Core/Stateflows/StateMachines/Registration/Interfaces/Extensions/TypedCompositeStateBuilder/StateMachine/TypedInitializedCompositeStateBuilderTypedExtensions.cs +++ b/Core/Stateflows/StateMachines/Registration/Interfaces/Extensions/TypedCompositeStateBuilder/StateMachine/TypedInitializedCompositeStateBuilderTypedExtensions.cs @@ -9,9 +9,7 @@ public static class TypedInitializedCompositeStateBuilderTypedExtensions { #region AddFinalState [DebuggerHidden] -#pragma warning disable S2326 // Unused type parameters should be removed public static ITypedFinalizedCompositeStateBuilder AddState(this ITypedInitializedCompositeStateBuilder builder, string stateName = FinalState.Name) -#pragma warning restore S2326 // Unused type parameters should be removed where TFinalState : FinalState => builder.AddFinalState(stateName); #endregion diff --git a/Core/Stateflows/StateMachines/Registration/Interfaces/Extensions/TypedStateMachineBuilder/StateMachine/TypedInitializedStateMachineBuilderTypedExtensions.cs b/Core/Stateflows/StateMachines/Registration/Interfaces/Extensions/TypedStateMachineBuilder/StateMachine/TypedInitializedStateMachineBuilderTypedExtensions.cs index 30468fb3..175f864b 100644 --- a/Core/Stateflows/StateMachines/Registration/Interfaces/Extensions/TypedStateMachineBuilder/StateMachine/TypedInitializedStateMachineBuilderTypedExtensions.cs +++ b/Core/Stateflows/StateMachines/Registration/Interfaces/Extensions/TypedStateMachineBuilder/StateMachine/TypedInitializedStateMachineBuilderTypedExtensions.cs @@ -9,9 +9,7 @@ public static class TypedInitializedStateMachineBuilderTypedExtensions { #region AddFinalState [DebuggerHidden] -#pragma warning disable S2326 // Unused type parameters should be removed public static ITypedFinalizedStateMachineBuilder AddState(this ITypedInitializedStateMachineBuilder builder, string stateName = FinalState.Name) -#pragma warning restore S2326 // Unused type parameters should be removed where TFinalState : FinalState => builder.AddFinalState(stateName); #endregion diff --git a/Core/Stateflows/System/Engine/Provider.cs b/Core/Stateflows/System/Engine/Provider.cs index 60da304c..5c4e5ef2 100644 --- a/Core/Stateflows/System/Engine/Provider.cs +++ b/Core/Stateflows/System/Engine/Provider.cs @@ -21,9 +21,7 @@ public Provider(StateflowsEngine engine, IServiceProvider serviceProvider) ServiceProvider = serviceProvider; } -#pragma warning disable CS0067 // The event 'Provider.BehaviorClassesChanged' is never used public event ActionAsync BehaviorClassesChanged; -#pragma warning restore CS0067 // The event 'Provider.BehaviorClassesChanged' is never used public bool TryProvideBehavior(BehaviorId id, out IBehavior behavior) { diff --git a/Examples/Blazor/Server/Blazor.Server/Pages/Activities.razor b/Examples/Blazor/Server/Blazor.Server/Pages/Activities.razor index 68e0e344..f300a112 100644 --- a/Examples/Blazor/Server/Blazor.Server/Pages/Activities.razor +++ b/Examples/Blazor/Server/Blazor.Server/Pages/Activities.razor @@ -137,7 +137,7 @@ private async Task RunActivity() { - if (locator.TryLocateActivity(new ActivityId("activity1", activityInstance), out var activity)) + if (locator.TryLocateActivity(GetCurrentId(), out var activity)) { await activity.InitializeAsync(); await RefreshAInfo(activity); @@ -150,7 +150,7 @@ private async Task PushActivity() { - if (locator.TryLocateActivity(new ActivityId("activity1", activityInstance), out var activity)) + if (locator.TryLocateActivity(GetCurrentId(), out var activity)) { await activity.SendAsync(new Examples.Common.SomeEvent()); } diff --git a/Examples/Blazor/Server/Blazor.Server/Program.cs b/Examples/Blazor/Server/Blazor.Server/Program.cs index 0697d285..4b9d1f29 100644 --- a/Examples/Blazor/Server/Blazor.Server/Program.cs +++ b/Examples/Blazor/Server/Blazor.Server/Program.cs @@ -19,6 +19,7 @@ using X; using System.Collections.Generic; using Newtonsoft.Json.Linq; +using MongoDB.Driver; var builder = WebApplication.CreateBuilder(args); @@ -45,7 +46,7 @@ ) ) .AddState("state2", b => b - .AddOnEntry(c => + .AddOnEntry(async c => { c.StateMachine.Publish(new SomeNotification()); }) @@ -80,7 +81,7 @@ .AddExceptionHandler(async c => { Debug.WriteLine(c.Exception.Message); - c.Output(new Token() { Payload = 666 }); + c.Output(666); }) .AddInitial(b => b .AddControlFlow("action1") @@ -88,15 +89,15 @@ ) .AddAction( "action1", - async c => c.Output(new Token { Payload = 42 }), + async c => c.Output(42), b => b - .AddFlow, Flow1>("action2") + .AddFlow("action2") ) .AddAction( "action2", async c => { - Debug.WriteLine(c.Input.OfType>().First().Payload); + Debug.WriteLine(c.GetTokensOfType().First()); throw new Exception("test"); }, b => b.AddControlFlow("action3") @@ -106,12 +107,37 @@ async c => { } ) - .AddFlow>("action4") + .AddFlow("action4") ) .AddAction("action4", async c => { }) ) .AddActivity("activity3") + + .AddActivity("activity4", b => b + .AddOnInitialize(async c => + { + Debug.WriteLine(c.InitializationRequest.Foo); + + return true; + }) + + .AddInitial(b => b + .AddControlFlow("1") + ) + .AddAction( + "1", + async c => c.OutputRange(Enumerable.Range(1, 10)), + b => b.AddFlow("2") + ) + .AddAction( + "2", + async c => Debug.WriteLine($"{c.GetTokensOfType().Count()}") + ) + .AddAcceptEventAction(b => b + .AddControlFlow("2") + ) + ) ) .AddAutoInitialization(new StateMachineClass("stateMachine1")) @@ -155,11 +181,6 @@ public class InitializationRequest1 : InitializationRequest public class Activity3 : Stateflows.Activities.Activity { - private async Task MethodAsync() - { - return; - } - public override void Build(ITypedActivityBuilder builder) => builder .AddAcceptEventAction(async c => { }, b => b @@ -167,29 +188,28 @@ public override void Build(ITypedActivityBuilder builder) ) .AddAction( "action1", - async c => c.OutputRange(Enumerable.Range(0, 100).ToTokens()), - b => b.AddFlow>("chunked") + async c => c.OutputRange(Enumerable.Range(0, 100)), + b => b.AddFlow("chunked") ) - - .AddParallelActivity>( + .AddParallelActivity( "chunked", b => b .AddInput(b => b - .AddFlow>("main") + .AddFlow("main") ) .AddAction( "main", async c => { - var tokens = c.Input.OfType>().Select(t => $"value: {t.Payload}").ToTokens(); + var tokens = c.GetTokensOfType().Select(t => $"value: {t}"); c.OutputRange(tokens); - Debug.WriteLine($"{tokens.Count()}/{c.Input.Count()} tokens: {string.Join(", ", c.Input.OfType>().Take(5).Select(t => t.Payload))}..."); + Debug.WriteLine($"{tokens.Count()}/{c.GetTokensOfType().Count()} tokens: {string.Join(", ", c.GetTokensOfType().Take(5))}..."); await Task.Delay(1000); }, - b => b.AddFlow>(OutputNode.Name) + b => b.AddFlow(OutputNode.Name) ) .AddOutput() - .AddFlow>("action2", b => b + .AddFlow("action2", b => b .AddGuard(async c => { lock (c.Activity.LockHandle) @@ -210,13 +230,9 @@ public override void Build(ITypedActivityBuilder builder) "action2", async c => { - Debug.WriteLine(c.Input.OfType>().Count().ToString()); + Debug.WriteLine(c.GetTokensOfType().Count().ToString()); c.Activity.Values.TryGet("count", out var counter); Debug.WriteLine($"counter: {counter}"); - //foreach (var token in c.Input.OfType>()) - //{ - // Debug.WriteLine(token.Payload); - //} } ); @@ -228,11 +244,30 @@ public override async Task OnInitializeAsync(InitializationRequest1 initia } } - public class Flow1 : Flow> + public class Action1 : ActionNode + { + public readonly Input IntInput; + + private readonly GlobalValue Foo = new("foo"); + + private readonly StateValue Bar = new("bar"); + + public override Task ExecuteAsync() + { + if (!Foo.IsSet) + { + Foo.Value = 42; + } + + return Task.CompletedTask; + } + } + + public class Flow1 : Flow { public override async Task GuardAsync() { - return Context.Token.Payload > 40; + return Context.Token > 40; } } } \ No newline at end of file diff --git a/Examples/MassTransit/MassTransit.Service2/Program.cs b/Examples/MassTransit/MassTransit.Service2/Program.cs index 97fac78e..a376137c 100644 --- a/Examples/MassTransit/MassTransit.Service2/Program.cs +++ b/Examples/MassTransit/MassTransit.Service2/Program.cs @@ -2,6 +2,7 @@ using MassTransit; using Stateflows; using Stateflows.StateMachines; +using Stateflows.StateMachines.Sync; using Examples.Common; var builder = WebApplication.CreateBuilder(args); diff --git a/Extensions/Stateflows.Extensions.Logging/ActivityTracer.cs b/Extensions/Stateflows.Extensions.Logging/ActivityTracer.cs new file mode 100644 index 00000000..4de41b67 --- /dev/null +++ b/Extensions/Stateflows.Extensions.Logging/ActivityTracer.cs @@ -0,0 +1,114 @@ +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Stateflows.Common; +using Stateflows.Activities; +using Stateflows.Activities.Context.Interfaces; + +namespace Stateflows.Extensions.Logging +{ + internal class ActivityTracer : IActivityObserver, IActivityInterceptor + { + private readonly ILogger logger; + + public ActivityTracer(ILogger logger) + { + this.logger = logger; + } + + public Task AfterActivityFinalizeAsync(IActivityFinalizationContext context) + { + logger.LogTrace("Activity {id}: behavior is finalized", context.Activity.Id); + + return Task.CompletedTask; + } + + public Task AfterActivityInitializeAsync(IActivityInitializationContext context) + { + logger.LogTrace("Activity {id}: behavior is initialized", context.Activity.Id); + + return Task.CompletedTask; + } + + public Task AfterFlowGuardAsync(IGuardContext context, bool guardResult) + { + return Task.CompletedTask; + } + + public Task AfterFlowTransformAsync(ITransformationContext context) + { + return Task.CompletedTask; + } + + public Task AfterNodeExecuteAsync(IActivityNodeContext context) + { + logger.LogTrace("Activity {id}: node {nodeName} is executed", context.Activity.Id, context.CurrentNode.NodeName); + + return Task.CompletedTask; + } + + public Task AfterNodeFinalizeAsync(IActivityNodeContext context) + { + return Task.CompletedTask; + } + + public Task AfterNodeInitializeAsync(IActivityNodeContext context) + { + return Task.CompletedTask; + } + + public Task BeforeActivityFinalizeAsync(IActivityFinalizationContext context) + { + return Task.CompletedTask; + } + + public Task BeforeActivityInitializeAsync(IActivityInitializationContext context) + { + return Task.CompletedTask; + } + + public Task BeforeFlowGuardAsync(IGuardContext context) + { + return Task.CompletedTask; + } + + public Task BeforeFlowTransformAsync(ITransformationContext context) + { + return Task.CompletedTask; + } + + public Task BeforeNodeExecuteAsync(IActivityNodeContext context) + { + return Task.CompletedTask; + } + + public Task BeforeNodeFinalizeAsync(IActivityNodeContext context) + { + return Task.CompletedTask; + } + + public Task BeforeNodeInitializeAsync(IActivityNodeContext context) + { + return Task.CompletedTask; + } + + public Task AfterHydrateAsync(IActivityActionContext context) + { + return Task.CompletedTask; + } + + public Task BeforeDehydrateAsync(IActivityActionContext context) + { + return Task.CompletedTask; + } + + public Task BeforeProcessEventAsync(IEventContext context) + { + return Task.FromResult(true); + } + + public Task AfterProcessEventAsync(IEventContext context) + { + return Task.CompletedTask; + } + } +} diff --git a/Extensions/Stateflows.Extensions.Logging/DependencyInjection.cs b/Extensions/Stateflows.Extensions.Logging/DependencyInjection.cs new file mode 100644 index 00000000..a1e7907a --- /dev/null +++ b/Extensions/Stateflows.Extensions.Logging/DependencyInjection.cs @@ -0,0 +1,17 @@ +using Stateflows.Activities; +using Stateflows.Common.Registration.Interfaces; +using Stateflows.Extensions.Logging; +using Stateflows.StateMachines; + +namespace Stateflows +{ + public static class DependencyInjection + { + public static IStateflowsBuilder AddTraceLogging(this IStateflowsBuilder stateflowsBuilder) + { + return stateflowsBuilder + .AddStateMachines(b => b.AddObserver()) + .AddActivities(b => b.AddObserver()); + } + } +} diff --git a/Extensions/Stateflows.Extensions.Logging/StateMachineTracer.cs b/Extensions/Stateflows.Extensions.Logging/StateMachineTracer.cs new file mode 100644 index 00000000..c3ea46e2 --- /dev/null +++ b/Extensions/Stateflows.Extensions.Logging/StateMachineTracer.cs @@ -0,0 +1,90 @@ +using Stateflows.Common; +using Stateflows.StateMachines; +using Stateflows.StateMachines.Context.Interfaces; +using System.Threading.Tasks; + +namespace Stateflows.Extensions.Logging +{ + internal class StateMachineTracer : IStateMachineObserver + { + public Task AfterStateEntryAsync(IStateActionContext context) + { + return Task.CompletedTask; + } + + public Task AfterStateExitAsync(IStateActionContext context) + { + return Task.CompletedTask; + } + + public Task AfterStateFinalizeAsync(IStateActionContext context) + { + return Task.CompletedTask; + } + + public Task AfterStateInitializeAsync(IStateActionContext context) + { + return Task.CompletedTask; + } + + public Task AfterStateMachineFinalizeAsync(IStateMachineActionContext context) + { + return Task.CompletedTask; + } + + public Task AfterStateMachineInitializeAsync(IStateMachineInitializationContext context) + { + return Task.CompletedTask; + } + + public Task AfterTransitionEffectAsync(ITransitionContext context) + { + return Task.CompletedTask; + } + + public Task AfterTransitionGuardAsync(IGuardContext context, bool guardResult) + { + return Task.CompletedTask; + } + + public Task BeforeStateEntryAsync(IStateActionContext context) + { + return Task.CompletedTask; + } + + public Task BeforeStateExitAsync(IStateActionContext context) + { + return Task.CompletedTask; + } + + public Task BeforeStateFinalizeAsync(IStateActionContext context) + { + return Task.CompletedTask; + } + + public Task BeforeStateInitializeAsync(IStateActionContext context) + { + return Task.CompletedTask; + } + + public Task BeforeStateMachineFinalizeAsync(IStateMachineActionContext context) + { + return Task.CompletedTask; + } + + public Task BeforeStateMachineInitializeAsync(IStateMachineInitializationContext context) + { + return Task.CompletedTask; + } + + public Task BeforeTransitionEffectAsync(ITransitionContext context) + { + return Task.CompletedTask; + } + + public Task BeforeTransitionGuardAsync(IGuardContext context) + { + return Task.CompletedTask; + } + } +} diff --git a/Extensions/Stateflows.Extensions.Logging/Stateflows.Extensions.Logging.csproj b/Extensions/Stateflows.Extensions.Logging/Stateflows.Extensions.Logging.csproj new file mode 100644 index 00000000..7627fa46 --- /dev/null +++ b/Extensions/Stateflows.Extensions.Logging/Stateflows.Extensions.Logging.csproj @@ -0,0 +1,12 @@ + + + + netstandard2.1 + enable + + + + + + + diff --git a/Extensions/Stateflows.Extensions.PlantUml/Classes/ActivityPlantUmlGenerator.cs b/Extensions/Stateflows.Extensions.PlantUml/Classes/ActivityPlantUmlGenerator.cs index 857c2b76..bb3651bc 100644 --- a/Extensions/Stateflows.Extensions.PlantUml/Classes/ActivityPlantUmlGenerator.cs +++ b/Extensions/Stateflows.Extensions.PlantUml/Classes/ActivityPlantUmlGenerator.cs @@ -4,6 +4,7 @@ using Stateflows.Activities; using Stateflows.Activities.Inspection.Interfaces; using Stateflows.Common; +using Stateflows.Common.Extensions; namespace Stateflows.Extensions.PlantUml.Classes { @@ -61,7 +62,7 @@ private static void GetPlantUml(int indentCount, INodeInspection node, StringBui var source = GetNodeName(transition.Source, parentName); var target = GetNodeName(transition.Target, parentName); - if (transition.TokenName == TokenInfo.Name) + if (transition.TokenName == typeof(Control).GetTokenName()) { builder.AppendLine($"{indent}{source} --> {target}"); } diff --git a/Locks/Stateflows.Locks.DistributedLock/Stateflows.Locks.DistributedLock.csproj b/Locks/Stateflows.Locks.DistributedLock/Stateflows.Locks.DistributedLock.csproj index ab3e9c1b..1e383126 100644 --- a/Locks/Stateflows.Locks.DistributedLock/Stateflows.Locks.DistributedLock.csproj +++ b/Locks/Stateflows.Locks.DistributedLock/Stateflows.Locks.DistributedLock.csproj @@ -36,8 +36,4 @@ - - - - diff --git a/Stateflows.sln b/Stateflows.sln index 75d74ba5..63ff772d 100644 --- a/Stateflows.sln +++ b/Stateflows.sln @@ -85,7 +85,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stateflows.Transport.Http", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stateflows.Transport.Http.Client", "Transport\Stateflows.Transport.Http.Client\Stateflows.Transport.Http.Client.csproj", "{37C61B16-A27E-487B-AEBC-126E7FDD8443}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Activity.IntegrationTests", "Tests\Activity.IntegrationTests\Activity.IntegrationTests.csproj", "{D6FD721E-4B42-4875-B774-2AD84BE5B3B6}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Activity.IntegrationTests", "Tests\Activity.IntegrationTests\Activity.IntegrationTests.csproj", "{D6FD721E-4B42-4875-B774-2AD84BE5B3B6}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C86A414E-4A16-4E38-AE1E-0193B3C236BD}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/Storage/Stateflows.Storage.EntityFrameworkCore/Stateflows.Storage.EntityFrameworkCore.csproj b/Storage/Stateflows.Storage.EntityFrameworkCore/Stateflows.Storage.EntityFrameworkCore.csproj index 0e2e2aa9..5ad630f5 100644 --- a/Storage/Stateflows.Storage.EntityFrameworkCore/Stateflows.Storage.EntityFrameworkCore.csproj +++ b/Storage/Stateflows.Storage.EntityFrameworkCore/Stateflows.Storage.EntityFrameworkCore.csproj @@ -47,8 +47,4 @@ - - - - diff --git a/Tests/Activity.IntegrationTests/Classes/Tokens/SomeToken.cs b/Tests/Activity.IntegrationTests/Classes/Tokens/SomeToken.cs new file mode 100644 index 00000000..d75b5ae3 --- /dev/null +++ b/Tests/Activity.IntegrationTests/Classes/Tokens/SomeToken.cs @@ -0,0 +1,7 @@ +namespace Activity.IntegrationTests.Classes.Tokens +{ + public class SomeToken + { + public string Foo { get; set; } + } +} diff --git a/Tests/Activity.IntegrationTests/Tests/AcceptEvent.cs b/Tests/Activity.IntegrationTests/Tests/AcceptEvent.cs new file mode 100644 index 00000000..87d856c8 --- /dev/null +++ b/Tests/Activity.IntegrationTests/Tests/AcceptEvent.cs @@ -0,0 +1,87 @@ +using Stateflows.Common; +using StateMachine.IntegrationTests.Utils; + +namespace Activity.IntegrationTests.Tests +{ + [TestClass] + public class AcceptEvent : StateflowsTestClass + { + private bool Executed = false; + private int Counter = 0; + + [TestInitialize] + public override void Initialize() + => base.Initialize(); + + [TestCleanup] + public override void Cleanup() + => base.Cleanup(); + + protected override void InitializeStateflows(IStateflowsBuilder builder) + { + builder + .AddActivities(b => b + .AddActivity("acceptSingleEvent", b => b + .AddInitial(b => b + .AddControlFlow("final") + .AddControlFlow("accept") + ) + .AddAcceptEventAction( + "accept", + async c => Counter++, + b => b.AddControlFlow("final") + ) + .AddAction("final", async c => + { + Executed = true; + }) + ) + .AddActivity("acceptMultipleEvents", b => b + .AddInitial(b => b + .AddControlFlow("final") + ) + .AddAcceptEventAction( + "accept", + async c => Counter++, + b => b.AddControlFlow("final") + ) + .AddAction("final", async c => + { + Executed = true; + }) + ) + ) + ; + } + + [TestMethod] + public async Task AcceptSingleEvent() + { + SendResult result = null; + if (ActivityLocator.TryLocateActivity(new ActivityId("acceptSingleEvent", "x"), out var a)) + { + await a.InitializeAsync(); + await a.SendAsync(new SomeEvent()); + result = await a.SendAsync(new SomeEvent()); + } + + Assert.IsTrue(Executed); + Assert.AreEqual(1, Counter); + Assert.AreEqual(EventStatus.NotConsumed, result?.Status); + } + + [TestMethod] + public async Task AcceptMultipleEvents() + { + if (ActivityLocator.TryLocateActivity(new ActivityId("acceptMultipleEvents", "x"), out var a)) + { + await a.InitializeAsync(); + await a.SendAsync(new SomeEvent()); + await a.SendAsync(new SomeEvent()); + } + + Assert.IsTrue(Executed); + Assert.AreEqual(2, Counter); + } + } +} \ No newline at end of file diff --git a/Tests/Activity.IntegrationTests/Tests/ActionUnit.cs b/Tests/Activity.IntegrationTests/Tests/ActionUnit.cs new file mode 100644 index 00000000..9563d781 --- /dev/null +++ b/Tests/Activity.IntegrationTests/Tests/ActionUnit.cs @@ -0,0 +1,75 @@ +using Stateflows.Common; +using Stateflows.Activities.Typed; +using StateMachine.IntegrationTests.Utils; + +namespace Activity.IntegrationTests.Tests +{ + public class TestedAction : ActionNode + { + private readonly GlobalValue Foo = new("foo"); + private readonly SingleInput Input; + + public override Task ExecuteAsync() + { + Foo.Set(Input.Token); + ActionUnit.Executed = true; + + return Task.CompletedTask; + } + } + + public class TestedFlow : Flow + { + public override Task GuardAsync() + { + return Task.FromResult(true); + } + } + + [TestClass] + public class ActionUnit : StateflowsTestClass + { + public static bool? Executed = null; + + [TestInitialize] + public override void Initialize() + => base.Initialize(); + + [TestCleanup] + public override void Cleanup() + => base.Cleanup(); + + protected override void InitializeStateflows(IStateflowsBuilder builder) + { + builder.AddActivities(b => b + .AddActivity("unit", b => b + .AddInitial(b => b + .AddControlFlow("generate") + ) + .AddAction( + "generate", + async c => c.Output(42), + b => b.AddFlow() + ) + .AddAction() + ) + ); + } + + [TestMethod] + public async Task ActionUnitTest() + { + var cradle = SetupCradle() + .AddInputToken(42) + .Build(); + + var results = await cradle.SwingAsync(); + + var isSet = results.TryGetGlobalContextValue("foo", out var value); + + Assert.IsTrue(isSet); + Assert.AreEqual(42, value); + Assert.IsTrue(Executed); + } + } +} \ No newline at end of file diff --git a/Tests/Activity.IntegrationTests/Tests/Context.cs b/Tests/Activity.IntegrationTests/Tests/Context.cs new file mode 100644 index 00000000..02efbd63 --- /dev/null +++ b/Tests/Activity.IntegrationTests/Tests/Context.cs @@ -0,0 +1,80 @@ +using Stateflows.Activities.Context.Interfaces; +using StateMachine.IntegrationTests.Utils; + +namespace Activity.IntegrationTests.Tests +{ + public class FlowObserver : IActivityObserver + { + public Task BeforeNodeActivateAsync(IActivityNodeContext context, bool activated) + { + if (context.CurrentNode.NodeName.EndsWith("action3")) + { + Context.ActivationAttempted = true; + Context.Activated1 = context.CurrentNode.IncomingFlows.First().Activated; + Context.Activated2 = context.CurrentNode.IncomingFlows.Last().Activated; + } + + return Task.CompletedTask; + } + } + + [TestClass] + public class Context : StateflowsTestClass + { + public static bool? ActivationAttempted = null; + public static bool? Executed = null; + public static bool? Activated1 = null; + public static bool? Activated2 = null; + + [TestInitialize] + public override void Initialize() + => base.Initialize(); + + [TestCleanup] + public override void Cleanup() + => base.Cleanup(); + + protected override void InitializeStateflows(IStateflowsBuilder builder) + { + builder + .AddActivities(b => b + .AddActivity("flow", b => b + .AddObserver() + .AddInitial(b => b + .AddControlFlow("action1") + .AddControlFlow("action2") + ) + .AddAction( + "action1", + async c => { }, + b => b.AddFlow("action3") + ) + .AddAction( + "action2", + async c => { }, + b => b.AddControlFlow("action3") + ) + .AddAction( + "action3", + async c => Executed = true + ) + ) + ) + ; + } + + [TestMethod] + public async Task FlowContext() + { + if (ActivityLocator.TryLocateActivity(new ActivityId("flow", "x"), out var a)) + { + await a.InitializeAsync(); + } + + Assert.IsFalse(Activated1); + Assert.IsTrue(Activated2); + Assert.IsTrue(ActivationAttempted); + Assert.AreNotEqual(true, Executed); + } + } +} \ No newline at end of file diff --git a/Tests/Activity.IntegrationTests/Tests/DataStore.cs b/Tests/Activity.IntegrationTests/Tests/DataStore.cs new file mode 100644 index 00000000..18fc68ca --- /dev/null +++ b/Tests/Activity.IntegrationTests/Tests/DataStore.cs @@ -0,0 +1,64 @@ +using Stateflows.Activities.Typed; +using StateMachine.IntegrationTests.Utils; + +namespace Activity.IntegrationTests.Tests +{ + [TestClass] + public class DataStore : StateflowsTestClass + { + private int ExecutionCount = 0; + private int TokenCount = 0; + + [TestInitialize] + public override void Initialize() + => base.Initialize(); + + [TestCleanup] + public override void Cleanup() + => base.Cleanup(); + + protected override void InitializeStateflows(IStateflowsBuilder builder) + { + builder + .AddActivities(b => b + .AddActivity("dataStore", b => b + .AddInitial(b => b + .AddControlFlow("generate") + ) + .AddAction( + "generate", + async c => c.OutputRange(Enumerable.Range(0, 10)), + b => b.AddFlow("dataStore") + ) + .AddDataStore("dataStore", b => b + .AddFlow("final") + ) + .AddAcceptEventAction(b => b + .AddControlFlow("final") + ) + .AddAction("final", async c => + { + ExecutionCount++; + TokenCount += c.GetTokensOfType().Count(); + }) + ) + ) + ; + } + + [TestMethod] + public async Task DataStored() + { + if (ActivityLocator.TryLocateActivity(new ActivityId("dataStore", "x"), out var a)) + { + await a.InitializeAsync(); + await a.SendAsync(new SomeEvent()); + await a.SendAsync(new SomeEvent()); + await a.SendAsync(new SomeEvent()); + } + + Assert.AreEqual(3, ExecutionCount); + Assert.AreEqual(30, TokenCount); + } + } +} \ No newline at end of file diff --git a/Tests/Activity.IntegrationTests/Tests/Decision.cs b/Tests/Activity.IntegrationTests/Tests/Decision.cs new file mode 100644 index 00000000..18b4d612 --- /dev/null +++ b/Tests/Activity.IntegrationTests/Tests/Decision.cs @@ -0,0 +1,100 @@ +using Stateflows.Activities.Typed; +using StateMachine.IntegrationTests.Utils; + +namespace Activity.IntegrationTests.Tests +{ + [TestClass] + public class Decision : StateflowsTestClass + { + private int ExecutionCount1 = 0; + private int TokenCount1 = 0; + private int ExecutionCount2 = 0; + private int TokenCount2 = 0; + private bool Execution1 = false; + private bool Execution2 = false; + + [TestInitialize] + public override void Initialize() + => base.Initialize(); + + [TestCleanup] + public override void Cleanup() + => base.Cleanup(); + + protected override void InitializeStateflows(IStateflowsBuilder builder) + { + builder + .AddActivities(b => b + .AddActivity("tokensDecision", b => b + .AddInitial(b => b + .AddControlFlow("generate") + ) + .AddAction( + "generate", + async c => c.OutputRange(Enumerable.Range(0, 10)), + b => b.AddFlow>() + ) + .AddDecision(b => b + .AddFlow("final1", b => b.AddGuard(async c => c.Token % 2 == 0)) + .AddElseFlow("final2") + ) + .AddAction("final1", async c => + { + ExecutionCount1++; + TokenCount1 += c.GetTokensOfType().Count(); + }) + .AddAction("final2", async c => + { + ExecutionCount2++; + TokenCount2 += c.GetTokensOfType().Count(); + }) + ) + .AddActivity("controlDecision", b => b + .AddInitial(b => b + .AddControlFlow("setup") + ) + .AddAction( + "setup", + async c => c.Activity.Values.Set("value", true), + b => b.AddControlFlow() + ) + .AddControlDecision(b => b + .AddFlow("final1", b => b + .AddGuard(async c => c.Activity.Values.TryGet("value", out var value) && value) + ) + .AddElseFlow("final2") + ) + .AddAction("final1", async c => Execution1 = true) + .AddAction("final2", async c => Execution2 = true) + ) + ) + ; + } + + [TestMethod] + public async Task TokenDecision() + { + if (ActivityLocator.TryLocateActivity(new ActivityId("tokensDecision", "x"), out var a)) + { + await a.InitializeAsync(); + } + + Assert.AreEqual(1, ExecutionCount1); + Assert.AreEqual(5, TokenCount1); + Assert.AreEqual(1, ExecutionCount2); + Assert.AreEqual(5, TokenCount2); + } + + [TestMethod] + public async Task ControlDecision() + { + if (ActivityLocator.TryLocateActivity(new ActivityId("controlDecision", "x"), out var a)) + { + await a.InitializeAsync(); + } + + Assert.IsTrue(Execution1); + Assert.IsFalse(Execution2); + } + } +} \ No newline at end of file diff --git a/Tests/Activity.IntegrationTests/Tests/Exceptions.cs b/Tests/Activity.IntegrationTests/Tests/Exceptions.cs index 007b52ac..3f6a89eb 100644 --- a/Tests/Activity.IntegrationTests/Tests/Exceptions.cs +++ b/Tests/Activity.IntegrationTests/Tests/Exceptions.cs @@ -1,16 +1,31 @@ -using Stateflows.Activities.Typed.Data; -using Stateflows.Activities.Data; -using Stateflows.Common; +using Stateflows.Activities.Typed; using StateMachine.IntegrationTests.Utils; namespace Activity.IntegrationTests.Tests { + public class SomeException : Exception + { + public SomeException(string? message) : base(message) { } + } + + public class OtherException : Exception + { + public OtherException(string? message) : base(message) { } + } + + public class Main : StructuredActivityNode + { + } + [TestClass] public class Exceptions : StateflowsTestClass { private bool Executed1 = false; private bool Executed2 = false; - public static string Value = "boo"; + private bool Executed3 = false; + private static string Value1 = "boo"; + private static string Value2 = "boo"; + private static string Value3 = "boo"; [TestInitialize] public override void Initialize() @@ -24,14 +39,18 @@ protected override void InitializeStateflows(IStateflowsBuilder builder) { builder .AddActivities(b => b - .AddActivity("handled", b => b + .AddActivity("specific", b => b .AddInitial(b => b .AddControlFlow("main") ) .AddStructuredActivity("main", b => b .AddExceptionHandler(async c => { - c.Output(new Token() { Payload = c.Exception.Message }); + c.Output("generic"); + }) + .AddExceptionHandler(async c => + { + c.Output(c.Exception.Message); }) .AddInitial(b => b .AddControlFlow("action1") @@ -39,10 +58,10 @@ protected override void InitializeStateflows(IStateflowsBuilder builder) .AddAction("action1", async c => { - c.Output(new Token() { Payload = 42 }); - throw new Exception("test"); + c.Output(42); + throw new SomeException("test"); }, - b => b.AddDataFlow("action2") + b => b.AddFlow("action2") ) .AddAction("action2", async c => @@ -50,29 +69,308 @@ protected override void InitializeStateflows(IStateflowsBuilder builder) Executed2 = true; } ) - .AddDataFlow("final") + .AddFlow("final") ) .AddAction("final", async c => { Executed1 = true; - Value = c.Input.OfType>().FirstOrDefault()?.Payload ?? "foo"; + Value1 = c.GetTokensOfType().FirstOrDefault() ?? "foo"; }) ) + .AddActivity("generic", b => b + .AddInitial(b => b + .AddControlFlow("main") + ) + .AddStructuredActivity("main", b => b + .AddExceptionHandler(async c => + { + c.Output(c.Exception.Message); + }) + .AddExceptionHandler(async c => + { + c.Output("specific"); + }) + .AddInitial(b => b + .AddControlFlow("action1") + ) + .AddAction("action1", + async c => + { + c.Output(42); + throw new OtherException("test"); + }, + b => b.AddFlow("action2") + ) + .AddAction("action2", + async c => + { + Executed2 = true; + } + ) + .AddFlow("final") + ) + .AddAction("final", async c => + { + Executed1 = true; + Value1 = c.GetTokensOfType().FirstOrDefault() ?? "foo"; + }) + ) + .AddActivity("structured", b => b + .AddInitial(b => b + .AddControlFlow("main") + ) + .AddStructuredActivity("main", b => b + .AddExceptionHandler(async c => + { + Executed2 = true; + Value1 = c.NodeOfOrigin.NodeName; + Value2 = c.ProtectedNode.NodeName; + }) + .AddInitial(b => b + .AddControlFlow("faulty") + ) + .AddAction("faulty", async c => + { + Executed1 = true; + throw new Exception(); + }) + ) + ) + .AddActivity("structured-typed", b => b + .AddInitial(b => b + .AddControlFlow
() + ) + .AddStructuredActivity
(b => b + .AddExceptionHandler(async c => + { + Executed2 = true; + Value1 = c.NodeOfOrigin.NodeName; + Value2 = c.ProtectedNode.NodeName; + }) + .AddInitial(b => b + .AddControlFlow("faulty") + ) + .AddAction("faulty", async c => + { + Executed1 = true; + throw new Exception(); + }) + ) + ) + .AddActivity("guard", b => b + .AddInitial(b => b + .AddControlFlow("faulty") + ) + .AddAction( + "faulty", + async c => { }, + b => b + .AddExceptionHandler(async c => + { + Executed2 = true; + Value1 = c.NodeOfOrigin.NodeName; + Value2 = c.ProtectedNode.NodeName; + }) + .AddControlFlow(b => b + .AddGuard(async c => + { + Executed1 = true; + throw new Exception(); + }) + ) + ) + .AddFinal() + ) + .AddActivity("plain", b => b + .AddInitial(b => b + .AddControlFlow("faulty") + ) + .AddAction( + "faulty", + async c => throw new Exception(), + b => b + .AddExceptionHandler(async c => + { + Executed1 = true; + Value1 = c.NodeOfOrigin.NodeName; + Value2 = c.ProtectedNode.NodeName; + }) + ) + ) + .AddActivity("plain-specific", b => b + .AddInitial(b => b + .AddControlFlow("faulty") + ) + .AddAction( + "faulty", + async c => throw new SomeException("foo"), + b => b + .AddExceptionHandler(async c => Executed1 = true) + .AddExceptionHandler(async c => Executed2 = true) + ) + ) + .AddActivity("plain-generic", b => b + .AddInitial(b => b + .AddControlFlow("faulty") + ) + .AddAction( + "faulty", + async c => throw new SomeException("foo"), + b => b + .AddExceptionHandler(async c => Executed1 = true) + ) + ) + .AddActivity("structured-guard", b => b + .AddInitial(b => b + .AddControlFlow("main") + ) + .AddStructuredActivity("main", b => b + .AddExceptionHandler(async c => + { + Executed2 = true; + Value1 = c.NodeOfOrigin.NodeName; + Value2 = c.ProtectedNode.NodeName; + Value3 = c.Exception?.Message; + }) + .AddInitial(b => b + .AddControlFlow("action1") + ) + .AddAction( + "action1", + async c => { }, + b => b + .AddControlFlow("action2", b => b + .AddGuard(async c => + { + Executed1 = true; + throw new Exception("foo"); + }) + ) + ) + .AddAction("action2", async c => + { + Executed3 = true; + }) + ) + ) ) ; } [TestMethod] - public async Task ExceptionHandled() + public async Task SpecificExceptionHandled() { - if (ActivityLocator.TryLocateActivity(new ActivityId("handled", "x"), out var a)) + if (ActivityLocator.TryLocateActivity(new ActivityId("specific", "x"), out var a)) { await a.InitializeAsync(); } Assert.IsTrue(Executed1); Assert.IsFalse(Executed2); - Assert.AreEqual("test", Value); + Assert.AreEqual("test", Value1); + } + + [TestMethod] + public async Task GenericExceptionHandled() + { + if (ActivityLocator.TryLocateActivity(new ActivityId("generic", "x"), out var a)) + { + await a.InitializeAsync(); + } + + Assert.IsTrue(Executed1); + Assert.IsFalse(Executed2); + Assert.AreEqual("test", Value1); + } + + [TestMethod] + public async Task StructuredExceptionHandled() + { + if (ActivityLocator.TryLocateActivity(new ActivityId("structured", "x"), out var a)) + { + await a.InitializeAsync(); + } + + Assert.IsTrue(Executed1); + Assert.IsTrue(Executed2); + Assert.AreEqual("main.faulty", Value1); + Assert.AreEqual("main", Value2); + } + + [TestMethod] + public async Task StructuredTypedExceptionHandled() + { + if (ActivityLocator.TryLocateActivity(new ActivityId("structured-typed", "x"), out var a)) + { + await a.InitializeAsync(); + } + + Assert.IsTrue(Executed1); + Assert.IsTrue(Executed2); + Assert.AreEqual("Activity.IntegrationTests.Tests.Main.faulty", Value1); + Assert.AreEqual("Activity.IntegrationTests.Tests.Main", Value2); + } + + [TestMethod] + public async Task StructuredGuardExceptionHandled() + { + if (ActivityLocator.TryLocateActivity(new ActivityId("structured-guard", "x"), out var a)) + { + await a.InitializeAsync(); + } + + Assert.IsTrue(Executed1); + Assert.IsTrue(Executed2); + Assert.AreEqual("main.action1", Value1); + Assert.AreEqual("main", Value2); + Assert.AreEqual("foo", Value3); + } + + [TestMethod] + public async Task PlainExceptionHandled() + { + if (ActivityLocator.TryLocateActivity(new ActivityId("plain", "x"), out var a)) + { + await a.InitializeAsync(); + } + + Assert.IsTrue(Executed1); + Assert.AreEqual("faulty", Value1); + } + + [TestMethod] + public async Task PlainSpecificExceptionHandled() + { + if (ActivityLocator.TryLocateActivity(new ActivityId("plain-specific", "x"), out var a)) + { + await a.InitializeAsync(); + } + + Assert.IsTrue(Executed2); + } + + [TestMethod] + public async Task PlainGenericExceptionHandled() + { + if (ActivityLocator.TryLocateActivity(new ActivityId("plain-generic", "x"), out var a)) + { + await a.InitializeAsync(); + } + + Assert.IsTrue(Executed1); + } + + [TestMethod] + public async Task GuardExceptionHandled() + { + if (ActivityLocator.TryLocateActivity(new ActivityId("guard", "x"), out var a)) + { + await a.InitializeAsync(); + } + + Assert.IsTrue(Executed1); + Assert.IsTrue(Executed2); + Assert.AreEqual("faulty", Value1); } } } \ No newline at end of file diff --git a/Tests/Activity.IntegrationTests/Tests/Fork.cs b/Tests/Activity.IntegrationTests/Tests/Fork.cs new file mode 100644 index 00000000..7dff6982 --- /dev/null +++ b/Tests/Activity.IntegrationTests/Tests/Fork.cs @@ -0,0 +1,56 @@ +using Stateflows.Activities.Typed; +using StateMachine.IntegrationTests.Utils; + +namespace Activity.IntegrationTests.Tests +{ + [TestClass] + public class Fork : StateflowsTestClass + { + private bool Execution1 = false; + private bool Execution2 = false; + + [TestInitialize] + public override void Initialize() + => base.Initialize(); + + [TestCleanup] + public override void Cleanup() + => base.Cleanup(); + + protected override void InitializeStateflows(IStateflowsBuilder builder) + { + builder + .AddActivities(b => b + .AddActivity("fork", b => b + .AddInitial(b => b + .AddControlFlow("generate") + ) + .AddAction( + "generate", + async c => c.OutputRange(Enumerable.Range(0, 10)), + b => b.AddFlow() + ) + .AddFork(b => b + .AddFlow("final1") + .AddFlow("final2") + ) + .AddAction("final1", async c => Execution1 = true) + .AddAction("final2", async c => Execution2 = true) + ) + ) + ; + } + + [TestMethod] + public async Task FlowForked() + { + if (ActivityLocator.TryLocateActivity(new ActivityId("fork", "x"), out var a)) + { + await a.InitializeAsync(); + } + + Assert.IsTrue(Execution1); + Assert.IsTrue(Execution2); + } + } +} \ No newline at end of file diff --git a/Tests/Activity.IntegrationTests/Tests/Initialization.cs b/Tests/Activity.IntegrationTests/Tests/Initialization.cs index ec1d1a1e..678abc36 100644 --- a/Tests/Activity.IntegrationTests/Tests/Initialization.cs +++ b/Tests/Activity.IntegrationTests/Tests/Initialization.cs @@ -85,7 +85,8 @@ public async Task SimpleInitialization() if (ActivityLocator.TryLocateActivity(new ActivityId("simple", "x"), out var a)) { - initialized = (await a.InitializeAsync()).Response.InitializationSuccessful; + var result = await a.InitializeAsync(); + initialized = result.Response.InitializationSuccessful; } Assert.IsTrue(initialized); diff --git a/Tests/Activity.IntegrationTests/Tests/Iterative.cs b/Tests/Activity.IntegrationTests/Tests/Iterative.cs new file mode 100644 index 00000000..f6858ba8 --- /dev/null +++ b/Tests/Activity.IntegrationTests/Tests/Iterative.cs @@ -0,0 +1,61 @@ +using StateMachine.IntegrationTests.Utils; + +namespace Activity.IntegrationTests.Tests +{ + [TestClass] + public class Iterative : StateflowsTestClass + { + private int ExecutionCounter = 0; + private int ExecutionSum = 0; + + [TestInitialize] + public override void Initialize() + => base.Initialize(); + + [TestCleanup] + public override void Cleanup() + => base.Cleanup(); + + protected override void InitializeStateflows(IStateflowsBuilder builder) + { + builder + .AddActivities(b => b + .AddActivity("iterative", b => b + .AddInitial(b => b + .AddControlFlow("generate") + ) + .AddAction("generate", + async c => c.OutputRange(Enumerable.Repeat(1, 100)), + b => b.AddFlow("iterative") + ) + .AddIterativeActivity("iterative", b => b + .AddInput(b => b + .AddFlow("action1") + ) + .AddAction("action1", + async c => + { + ExecutionCounter++; + ExecutionSum += c.GetTokensOfType().Sum(); + } + ), + 5 + ) + ) + ) + ; + } + + [TestMethod] + public async Task BasicIterativeActivity() + { + if (ActivityLocator.TryLocateActivity(new ActivityId("iterative", "x"), out var a)) + { + await a.InitializeAsync(); + } + + Assert.AreEqual(20, ExecutionCounter); + Assert.AreEqual(100, ExecutionSum); + } + } +} \ No newline at end of file diff --git a/Tests/Activity.IntegrationTests/Tests/Join.cs b/Tests/Activity.IntegrationTests/Tests/Join.cs new file mode 100644 index 00000000..e25482c9 --- /dev/null +++ b/Tests/Activity.IntegrationTests/Tests/Join.cs @@ -0,0 +1,62 @@ +using Stateflows.Activities.Typed; +using StateMachine.IntegrationTests.Utils; + +namespace Activity.IntegrationTests.Tests +{ + [TestClass] + public class Join : StateflowsTestClass + { + private int ExecutionCount = 0; + private int TokenCount = 0; + + [TestInitialize] + public override void Initialize() + => base.Initialize(); + + [TestCleanup] + public override void Cleanup() + => base.Cleanup(); + + protected override void InitializeStateflows(IStateflowsBuilder builder) + { + builder + .AddActivities(b => b + .AddActivity("join", b => b + .AddInitial(b => b + .AddControlFlow("generate1") + .AddControlFlow("generate2") + ) + .AddAction( + "generate1", + async c => c.OutputRange(Enumerable.Range(0, 10)), + b => b.AddFlow() + ) + .AddAction( + "generate2", + async c => c.OutputRange(Enumerable.Range(0, 10)), + b => b.AddFlow() + ) + .AddJoin(b => b.AddFlow("final")) + .AddAction("final", async c => + { + ExecutionCount++; + TokenCount += c.GetTokensOfType().Count(); + }) + ) + ) + ; + } + + [TestMethod] + public async Task FlowsJoined() + { + if (ActivityLocator.TryLocateActivity(new ActivityId("join", "x"), out var a)) + { + await a.InitializeAsync(); + } + + Assert.AreEqual(1, ExecutionCount); + Assert.AreEqual(20, TokenCount); + } + } +} \ No newline at end of file diff --git a/Tests/Activity.IntegrationTests/Tests/Merge.cs b/Tests/Activity.IntegrationTests/Tests/Merge.cs new file mode 100644 index 00000000..4d98a02c --- /dev/null +++ b/Tests/Activity.IntegrationTests/Tests/Merge.cs @@ -0,0 +1,62 @@ +using Stateflows.Activities.Typed; +using StateMachine.IntegrationTests.Utils; + +namespace Activity.IntegrationTests.Tests +{ + [TestClass] + public class Merge : StateflowsTestClass + { + private int ExecutionCount = 0; + private int TokenCount = 0; + + [TestInitialize] + public override void Initialize() + => base.Initialize(); + + [TestCleanup] + public override void Cleanup() + => base.Cleanup(); + + protected override void InitializeStateflows(IStateflowsBuilder builder) + { + builder + .AddActivities(b => b + .AddActivity("merge", b => b + .AddInitial(b => b + .AddControlFlow("generate1") + .AddControlFlow("generate2") + ) + .AddAction( + "generate1", + async c => c.OutputRange(Enumerable.Range(0, 10)), + b => b.AddFlow() + ) + .AddAction( + "generate2", + async c => c.OutputRange(Enumerable.Range(0, 10)), + b => b.AddFlow() + ) + .AddMerge(b => b.AddFlow("final")) + .AddAction("final", async c => + { + ExecutionCount++; + TokenCount += c.GetTokensOfType().Count(); + }) + ) + ) + ; + } + + [TestMethod] + public async Task FlowsMerged() + { + if (ActivityLocator.TryLocateActivity(new ActivityId("merge", "x"), out var a)) + { + await a.InitializeAsync(); + } + + Assert.AreEqual(2, ExecutionCount); + Assert.AreEqual(20, TokenCount); + } + } +} \ No newline at end of file diff --git a/Tests/Activity.IntegrationTests/Tests/Output.cs b/Tests/Activity.IntegrationTests/Tests/Output.cs index f7d214f3..7e759622 100644 --- a/Tests/Activity.IntegrationTests/Tests/Output.cs +++ b/Tests/Activity.IntegrationTests/Tests/Output.cs @@ -1,7 +1,7 @@ -using Stateflows.Activities.Typed.Data; -using Stateflows.Activities.Data; +using Stateflows.Activities.Typed; using Stateflows.Common; using StateMachine.IntegrationTests.Utils; +using System.Diagnostics; namespace Activity.IntegrationTests.Tests { @@ -9,8 +9,6 @@ namespace Activity.IntegrationTests.Tests public class Output : StateflowsTestClass { private bool Executed1 = false; - private bool Executed2 = false; - public static string Value = "boo"; [TestInitialize] public override void Initialize() @@ -35,16 +33,19 @@ protected override void InitializeStateflows(IStateflowsBuilder builder) .AddAction("action1", async c => { - c.Output(new Token() { Payload = 42 }); + c.Output(42); }, - b => b.AddDataFlow() + b => b.AddFlow() ) .AddOutput() - .AddDataFlow("final") + .AddFlow("final") + ) + .AddAcceptEventAction(b => b + .AddControlFlow("final") ) .AddAction("final", async c => { - Executed1 = c.Input.OfType>().Any(); + Executed1 = c.GetTokensOfType().Any(); }) ) ) @@ -52,11 +53,12 @@ protected override void InitializeStateflows(IStateflowsBuilder builder) } [TestMethod] - public async Task ExceptionHandled() + public async Task OutputFromStructuredActivity() { if (ActivityLocator.TryLocateActivity(new ActivityId("structured", "x"), out var a)) { await a.InitializeAsync(); + await a.SendAsync(new SomeEvent()); } Assert.IsTrue(Executed1); diff --git a/Tests/Activity.IntegrationTests/Tests/Parallel.cs b/Tests/Activity.IntegrationTests/Tests/Parallel.cs new file mode 100644 index 00000000..7998c642 --- /dev/null +++ b/Tests/Activity.IntegrationTests/Tests/Parallel.cs @@ -0,0 +1,64 @@ +using StateMachine.IntegrationTests.Utils; + +namespace Activity.IntegrationTests.Tests +{ + [TestClass] + public class Parallel : StateflowsTestClass + { + private int ExecutionCounter = 0; + private int ExecutionSum = 0; + + [TestInitialize] + public override void Initialize() + => base.Initialize(); + + [TestCleanup] + public override void Cleanup() + => base.Cleanup(); + + protected override void InitializeStateflows(IStateflowsBuilder builder) + { + builder + .AddActivities(b => b + .AddActivity("parallel", b => b + .AddInitial(b => b + .AddControlFlow("generate") + ) + .AddAction("generate", + async c => c.OutputRange(Enumerable.Repeat(1, 100)), + b => b.AddFlow("parallel") + ) + .AddParallelActivity("parallel", b => b + .AddInput(b => b + .AddFlow("action1") + ) + .AddAction("action1", + async c => + { + lock (this) + { + ExecutionCounter++; + ExecutionSum += c.GetTokensOfType().Sum(); + } + } + ), + 5 + ) + ) + ) + ; + } + + [TestMethod] + public async Task BasicParallelActivity() + { + if (ActivityLocator.TryLocateActivity(new ActivityId("parallel", "x"), out var a)) + { + await a.InitializeAsync(); + } + + Assert.AreEqual(20, ExecutionCounter); + Assert.AreEqual(100, ExecutionSum); + } + } +} \ No newline at end of file diff --git a/Tests/Activity.IntegrationTests/Tests/Structured.cs b/Tests/Activity.IntegrationTests/Tests/Structured.cs new file mode 100644 index 00000000..9ecbbb0b --- /dev/null +++ b/Tests/Activity.IntegrationTests/Tests/Structured.cs @@ -0,0 +1,134 @@ +using Stateflows.Common; +using Stateflows.Common.Data; +using StateMachine.IntegrationTests.Utils; + +namespace Activity.IntegrationTests.Tests +{ + [TestClass] + public class Structured : StateflowsTestClass + { + private bool Executed = false; + private int Counter = 0; + private readonly object LockHandle = new(); + + [TestInitialize] + public override void Initialize() + => base.Initialize(); + + [TestCleanup] + public override void Cleanup() + => base.Cleanup(); + + protected override void InitializeStateflows(IStateflowsBuilder builder) + { + builder + .AddActivities(b => b + .AddActivity("structured", b => b + .AddInitial(b => b + .AddControlFlow("generate") + ) + .AddAction( + "generate", + async c => c.OutputRange(Enumerable.Range(0, 10)), + b => b.AddFlow("main") + ) + .AddStructuredActivity("main", b => b + .AddInitial(b => b + .AddControlFlow("action1") + ) + .AddAction("action1", async c => { }) + .AddControlFlow("final") + ) + .AddAction("final", async c => + { + Executed = true; + }) + ) + .AddActivity("parallel", b => b + .AddInitial(b => b + .AddControlFlow("generate") + ) + .AddAction( + "generate", + async c => c.OutputRange(Enumerable.Range(0, 10)), + b => b.AddFlow("main") + ) + .AddParallelActivity("main", b => b + .AddInitial(b => b + .AddControlFlow("action1") + ) + .AddAction("action1", async c => + { + lock (LockHandle) + { + Counter++; + } + }) + .AddControlFlow("final") + ) + .AddAction("final", async c => + { + Executed = true; + }) + ) + .AddActivity("iterative", b => b + .AddInitial(b => b + .AddControlFlow("generate") + ) + .AddAction( + "generate", + async c => c.OutputRange(Enumerable.Range(0, 10)), + b => b.AddFlow("main") + ) + .AddParallelActivity("main", b => b + .AddInitial(b => b + .AddControlFlow("action1") + ) + .AddAction("action1", async c => Counter++) + .AddControlFlow("final") + ) + .AddAction("final", async c => + { + Executed = true; + }) + ) + ) + ; + } + + [TestMethod] + public async Task StructuredActivityFinished() + { + if (ActivityLocator.TryLocateActivity(new ActivityId("structured", "x"), out var a)) + { + await a.InitializeAsync(); + } + + Assert.IsTrue(Executed); + } + + [TestMethod] + public async Task ParallelActivityFinished() + { + if (ActivityLocator.TryLocateActivity(new ActivityId("parallel", "x"), out var a)) + { + await a.InitializeAsync(); + } + + Assert.IsTrue(Executed); + Assert.AreEqual(10, Counter); + } + + [TestMethod] + public async Task IterativeActivityFinished() + { + if (ActivityLocator.TryLocateActivity(new ActivityId("iterative", "x"), out var a)) + { + await a.InitializeAsync(); + } + + Assert.IsTrue(Executed); + Assert.AreEqual(10, Counter); + } + } +} \ No newline at end of file diff --git a/Tests/Activity.IntegrationTests/Tests/TokenIdentity.cs b/Tests/Activity.IntegrationTests/Tests/TokenIdentity.cs new file mode 100644 index 00000000..d915eb3e --- /dev/null +++ b/Tests/Activity.IntegrationTests/Tests/TokenIdentity.cs @@ -0,0 +1,65 @@ +using Stateflows.Common; +using Stateflows.Common.Data; +using StateMachine.IntegrationTests.Utils; + +namespace Activity.IntegrationTests.Tests +{ + [TestClass] + public class TokenIdentity : StateflowsTestClass + { + private int Count = -1; + + [TestInitialize] + public override void Initialize() + => base.Initialize(); + + [TestCleanup] + public override void Cleanup() + => base.Cleanup(); + + protected override void InitializeStateflows(IStateflowsBuilder builder) + { + builder + .AddActivities(b => b + .AddActivity("identity", b => b + .AddInitial(b => b + .AddControlFlow("generate") + ) + .AddAction( + "generate", + async c => c.OutputRange(Enumerable.Range(0, 10)), + b => b + .AddFlow("process1") + .AddFlow("process2") + ) + .AddAction( + "process1", + async c => c.PassAllTokensOn(), + b => b.AddFlow("join") + ) + .AddAction( + "process2", + async c => c.PassAllTokensOn(), + b => b.AddFlow("join") + ) + .AddAction("join", async c => + { + Count = c.GetTokensOfType().Count(); + }) + ) + ) + ; + } + + [TestMethod] + public async Task TokensNotDuplicated() + { + if (ActivityLocator.TryLocateActivity(new ActivityId("identity", "x"), out var a)) + { + await a.InitializeAsync(); + } + + Assert.AreEqual(10, Count); + } + } +} \ No newline at end of file diff --git a/Tests/Activity.IntegrationTests/Tests/Typed.cs b/Tests/Activity.IntegrationTests/Tests/Typed.cs new file mode 100644 index 00000000..7ea12273 --- /dev/null +++ b/Tests/Activity.IntegrationTests/Tests/Typed.cs @@ -0,0 +1,84 @@ +using Activity.IntegrationTests.Classes.Tokens; +using Stateflows.Activities.Typed; +using Stateflows.Common; +using StateMachine.IntegrationTests.Utils; + +namespace Activity.IntegrationTests.Tests +{ + public class TypedAction : ActionNode + { + public readonly Input someTokens; + public readonly Input strings; + + public readonly GlobalValue value = new("global"); + + public override Task ExecuteAsync() + { + Typed.TokenValue = someTokens.First().Foo; + + value.Set("foo"); + + return Task.CompletedTask; + } + } + + [TestClass] + public class Typed : StateflowsTestClass + { + private bool Executed = false; + public static string TokenValue = string.Empty; + + [TestInitialize] + public override void Initialize() + => base.Initialize(); + + [TestCleanup] + public override void Cleanup() + => base.Cleanup(); + + protected override void InitializeStateflows(IStateflowsBuilder builder) + { + builder + .AddActivities(b => b + .AddActivity("typed", b => b + .AddInitial(b => b + .AddControlFlow("main") + ) + .AddStructuredActivity("main", b => b + .AddInitial(b => b + .AddControlFlow("initial") + ) + .AddAction( + "initial", + async c => + { + c.Output(new SomeToken() { Foo = "bar" }); + c.Output("boo"); + }, + b => b + .AddFlow() + .AddFlow() + ) + .AddAction(b => b + .AddControlFlow("final") + ) + .AddAction("final", async c => Executed = true) + ) + ) + ) + ; + } + + [TestMethod] + public async Task InputVerification() + { + if (ActivityLocator.TryLocateActivity(new ActivityId("typed", "x"), out var a)) + { + await a.InitializeAsync(); + } + + Assert.IsTrue(Executed); + Assert.AreEqual("bar", TokenValue); + } + } +} \ No newline at end of file diff --git a/Tests/Activity.IntegrationTests/Tests/Values.cs b/Tests/Activity.IntegrationTests/Tests/Values.cs new file mode 100644 index 00000000..56a2bcc7 --- /dev/null +++ b/Tests/Activity.IntegrationTests/Tests/Values.cs @@ -0,0 +1,63 @@ +using Stateflows.Activities.Typed; +using Stateflows.Common; +using StateMachine.IntegrationTests.Utils; + +namespace Activity.IntegrationTests.Tests +{ + public class ValueAction : ActionNode + { + internal readonly GlobalValue globalCounter = new("x"); + + public override Task ExecuteAsync() + { + globalCounter.Set(42); + + return Task.CompletedTask; + } + } + + [TestClass] + public class Values : StateflowsTestClass + { + private bool Executed = false; + + [TestInitialize] + public override void Initialize() + => base.Initialize(); + + [TestCleanup] + public override void Cleanup() + => base.Cleanup(); + + protected override void InitializeStateflows(IStateflowsBuilder builder) + { + builder + .AddActivities(b => b + .AddActivity("values", b => b + .AddInitial(b => b + .AddControlFlow() + ) + .AddAction(b => b + .AddControlFlow("action2") + ) + .AddAction("action2", async c => + { + Executed = c.Activity.Values.TryGet("x", out int globalCounter) && globalCounter == 42; + }) + ) + ) + ; + } + + [TestMethod] + public async Task ValuesManagement() + { + if (ActivityLocator.TryLocateActivity(new ActivityId("values", "x"), out var a)) + { + await a.InitializeAsync(); + } + + Assert.IsTrue(Executed); + } + } +} \ No newline at end of file diff --git a/Tests/Activity.IntegrationTests/Tests/Weight.cs b/Tests/Activity.IntegrationTests/Tests/Weight.cs new file mode 100644 index 00000000..26cb378f --- /dev/null +++ b/Tests/Activity.IntegrationTests/Tests/Weight.cs @@ -0,0 +1,76 @@ +using StateMachine.IntegrationTests.Utils; + +namespace Activity.IntegrationTests.Tests +{ + [TestClass] + public class Weight : StateflowsTestClass + { + private bool Executed = false; + + [TestInitialize] + public override void Initialize() + => base.Initialize(); + + [TestCleanup] + public override void Cleanup() + => base.Cleanup(); + + protected override void InitializeStateflows(IStateflowsBuilder builder) + { + builder + .AddActivities(b => b + .AddActivity("optional", b => b + .AddInitial(b => b + .AddControlFlow("generate") + ) + .AddAction( + "generate", + async c => { }, + b => b.AddFlow("final", b => b.SetWeight(0)) + ) + .AddAction("final", async c => + { + Executed = true; + }) + ) + .AddActivity("required", b => b + .AddInitial(b => b + .AddControlFlow("generate") + ) + .AddAction( + "generate", + async c => c.OutputRange(Enumerable.Range(0, 5)), + b => b.AddFlow("final", b => b.SetWeight(10)) + ) + .AddAction("final", async c => + { + Executed = true; + }) + ) + ) + ; + } + + [TestMethod] + public async Task OptionalFlow() + { + if (ActivityLocator.TryLocateActivity(new ActivityId("optional", "x"), out var a)) + { + await a.InitializeAsync(); + } + + Assert.IsTrue(Executed); + } + + [TestMethod] + public async Task RequiredFlow() + { + if (ActivityLocator.TryLocateActivity(new ActivityId("required", "x"), out var a)) + { + await a.InitializeAsync(); + } + + Assert.IsFalse(Executed); + } + } +} \ No newline at end of file diff --git a/Tests/StateMachine/StateMachine.IntegrationTests/Classes/StateMachines/ValuesStateMachine.cs b/Tests/StateMachine/StateMachine.IntegrationTests/Classes/StateMachines/ValuesStateMachine.cs new file mode 100644 index 00000000..6b1054ba --- /dev/null +++ b/Tests/StateMachine/StateMachine.IntegrationTests/Classes/StateMachines/ValuesStateMachine.cs @@ -0,0 +1,21 @@ +using Stateflows.StateMachines.Typed; +using StateMachine.IntegrationTests.Classes.States; +using StateMachine.IntegrationTests.Classes.Transitions; + +namespace StateMachine.IntegrationTests.Classes.StateMachines +{ + public class ValuesStateMachine : Stateflows.StateMachines.StateMachine + { + public override void Build(ITypedStateMachineBuilder builder) + => builder + .AddInitialState(b => b + .AddDefaultTransition() + ) + .AddState(b => b + .AddInternalTransition() + .AddDefaultTransition() + ) + .AddFinalState() + ; + } +} diff --git a/Tests/StateMachine/StateMachine.IntegrationTests/Classes/States/ValueState1.cs b/Tests/StateMachine/StateMachine.IntegrationTests/Classes/States/ValueState1.cs new file mode 100644 index 00000000..5264c688 --- /dev/null +++ b/Tests/StateMachine/StateMachine.IntegrationTests/Classes/States/ValueState1.cs @@ -0,0 +1,21 @@ +using Stateflows.Common; + +namespace StateMachine.IntegrationTests.Classes.States +{ + internal class ValueState1 : State + { + private readonly StateValue counter = new("counter"); + + public override Task OnEntryAsync() + { + if (counter.TryGet(out var c)) + { + c = 0; + } + + counter.Set(c + 1); + + return Task.CompletedTask; + } + } +} diff --git a/Tests/StateMachine/StateMachine.IntegrationTests/Classes/States/ValueState2.cs b/Tests/StateMachine/StateMachine.IntegrationTests/Classes/States/ValueState2.cs new file mode 100644 index 00000000..b436da1b --- /dev/null +++ b/Tests/StateMachine/StateMachine.IntegrationTests/Classes/States/ValueState2.cs @@ -0,0 +1,10 @@ +namespace StateMachine.IntegrationTests.Classes.States +{ + internal class ValueState2 : State + { + public override Task OnEntryAsync() + { + return Task.CompletedTask; + } + } +} diff --git a/Tests/StateMachine/StateMachine.IntegrationTests/Classes/Transitions/GuardedTransition.cs b/Tests/StateMachine/StateMachine.IntegrationTests/Classes/Transitions/GuardedTransition.cs new file mode 100644 index 00000000..921a8d51 --- /dev/null +++ b/Tests/StateMachine/StateMachine.IntegrationTests/Classes/Transitions/GuardedTransition.cs @@ -0,0 +1,16 @@ +using Stateflows.Common; +using Stateflows.StateMachines.Events; + +namespace StateMachine.IntegrationTests.Classes.Transitions +{ + internal class GuardedTransition : Transition + { + private readonly GlobalValue counter = new("counter"); + + public override Task GuardAsync() + { + var result = counter.TryGet(out var c) && c == 1; + return Task.FromResult(result); + } + } +} diff --git a/Tests/StateMachine/StateMachine.IntegrationTests/Classes/Transitions/InternalTransition.cs b/Tests/StateMachine/StateMachine.IntegrationTests/Classes/Transitions/InternalTransition.cs new file mode 100644 index 00000000..a37fa70c --- /dev/null +++ b/Tests/StateMachine/StateMachine.IntegrationTests/Classes/Transitions/InternalTransition.cs @@ -0,0 +1,21 @@ +using Stateflows.Common; + +namespace StateMachine.IntegrationTests.Classes.Transitions +{ + internal class InternalTransition : Transition + { + private readonly GlobalValue counter = new("counter"); + + public override Task EffectAsync() + { + if (!counter.TryGet(out var c)) + { + c = 0; + } + + counter.Set(c + 1); + + return Task.CompletedTask; + } + } +} diff --git a/Tests/StateMachine/StateMachine.IntegrationTests/Classes/Transitions/ValueTransition.cs b/Tests/StateMachine/StateMachine.IntegrationTests/Classes/Transitions/ValueTransition.cs new file mode 100644 index 00000000..8ebb5028 --- /dev/null +++ b/Tests/StateMachine/StateMachine.IntegrationTests/Classes/Transitions/ValueTransition.cs @@ -0,0 +1,15 @@ +using Stateflows.StateMachines.Events; + +namespace StateMachine.IntegrationTests.Classes.Transitions +{ + internal class ValueTransition : Transition + { + private readonly SourceStateValue counter = new("counter"); + + public override Task GuardAsync() + { + var result = counter.TryGet(out var c) && c == 1; + return Task.FromResult(result); + } + } +} diff --git a/Tests/StateMachine/StateMachine.IntegrationTests/Tests/Composite.cs b/Tests/StateMachine/StateMachine.IntegrationTests/Tests/Composite.cs index bd49652c..58e2316b 100644 --- a/Tests/StateMachine/StateMachine.IntegrationTests/Tests/Composite.cs +++ b/Tests/StateMachine/StateMachine.IntegrationTests/Tests/Composite.cs @@ -128,7 +128,7 @@ public async Task DefaultTransition() if (StateMachineLocator.TryLocateStateMachine(new StateMachineId("default", "x"), out var sm)) { - var initRes = await sm.InitializeAsync(); + _ = await sm.InitializeAsync(); status = (await sm.SendAsync(new OtherEvent() { AnswerToLifeUniverseAndEverything = 42 })).Status; diff --git a/Tests/StateMachine/StateMachine.IntegrationTests/Tests/Context.cs b/Tests/StateMachine/StateMachine.IntegrationTests/Tests/Context.cs new file mode 100644 index 00000000..136de62e --- /dev/null +++ b/Tests/StateMachine/StateMachine.IntegrationTests/Tests/Context.cs @@ -0,0 +1,69 @@ +using StateMachine.IntegrationTests.Utils; + +namespace StateMachine.IntegrationTests.Tests +{ + public enum Foo + { + First = 0, + Last = 1 + } + + [TestClass] + public class Context : StateflowsTestClass + { + public bool EnumGet = false; + public bool IntGet = false; + public Foo EnumValue = Foo.First; + public int IntValue = 0; + + [TestInitialize] + public override void Initialize() + => base.Initialize(); + + [TestCleanup] + public override void Cleanup() + => base.Cleanup(); + + protected override void InitializeStateflows(IStateflowsBuilder builder) + { + builder + .AddStateMachines(b => b + .AddStateMachine("context", b => b + .AddInitialState("state1", b => b + .AddOnEntry(async c => c.StateMachine.Values.Set(nameof(Foo), Foo.Last)) + .AddDefaultTransition("state2") + ) + .AddState("state2", b => b + .AddOnEntry(async c => + { + if (c.StateMachine.Values.TryGet(nameof(Foo), out EnumValue)) + { + EnumGet = true; + } + + if (c.StateMachine.Values.TryGet(nameof(Foo), out IntValue)) + { + IntGet = true; + } + }) + ) + ) + ) + ; + } + + [TestMethod] + public async Task EnumSerialization() + { + if (StateMachineLocator.TryLocateStateMachine(new StateMachineId("context", "x"), out var stateMachine)) + { + await stateMachine.InitializeAsync(); + } + + Assert.IsTrue(EnumGet); + Assert.IsTrue(IntGet); + Assert.AreEqual(Foo.Last, EnumValue); + Assert.AreEqual((int)Foo.Last, IntValue); + } + } +} \ No newline at end of file diff --git a/Tests/StateMachine/StateMachine.IntegrationTests/Tests/Values.cs b/Tests/StateMachine/StateMachine.IntegrationTests/Tests/Values.cs new file mode 100644 index 00000000..5679babc --- /dev/null +++ b/Tests/StateMachine/StateMachine.IntegrationTests/Tests/Values.cs @@ -0,0 +1,43 @@ +using StateMachine.IntegrationTests.Classes.StateMachines; +using StateMachine.IntegrationTests.Classes.States; +using StateMachine.IntegrationTests.Utils; + +namespace StateMachine.IntegrationTests.Tests +{ + [TestClass] + public class Values : StateflowsTestClass + { + [TestInitialize] + public override void Initialize() + => base.Initialize(); + + [TestCleanup] + public override void Cleanup() + => base.Cleanup(); + + protected override void InitializeStateflows(IStateflowsBuilder builder) + { + builder + .AddStateMachines(b => b + .AddStateMachine() + ) + ; + } + + [TestMethod] + public async Task TypedStateMachine() + { + string currentState = StateInfo.Name; + + if (StateMachineLocator.TryLocateStateMachine(new StateMachineId(StateMachineInfo.Name, "x"), out var sm)) + { + await sm.InitializeAsync(); + await sm.SendAsync(new SomeEvent()); + + currentState = (await sm.GetCurrentStateAsync()).Response.StatesStack.First(); + } + + Assert.AreEqual(StateInfo.Name, currentState); + } + } +} \ No newline at end of file diff --git a/Transport/@stateflows/common/package.json b/Transport/@stateflows/common/package.json index d4318f74..8afee7cc 100644 --- a/Transport/@stateflows/common/package.json +++ b/Transport/@stateflows/common/package.json @@ -1,6 +1,6 @@ { "name": "@stateflows/common", - "version": "0.11.2", + "version": "0.12.0", "description": "Common package for Stateflows framework clients", "main": "dist/index.js", "module": "./dist/index.mjs", diff --git a/Transport/@stateflows/http-client/package.json b/Transport/@stateflows/http-client/package.json index cca5c52a..894a0b43 100644 --- a/Transport/@stateflows/http-client/package.json +++ b/Transport/@stateflows/http-client/package.json @@ -1,6 +1,6 @@ { "name": "@stateflows/http-client", - "version": "0.10.0", + "version": "0.12.0", "description": "HTTP-based client for Stateflows framework", "main": "dist/index.js", "module": "./dist/index.mjs", @@ -27,6 +27,6 @@ "typescript": "^5.3.3" }, "dependencies": { - "@stateflows/common": "^0.11.2" + "@stateflows/common": "^0.12.0" } } diff --git a/Transport/@stateflows/signalr-client/package.json b/Transport/@stateflows/signalr-client/package.json index bbc42df0..7a5414ef 100644 --- a/Transport/@stateflows/signalr-client/package.json +++ b/Transport/@stateflows/signalr-client/package.json @@ -1,6 +1,6 @@ { "name": "@stateflows/signalr-client", - "version": "0.10.0", + "version": "0.12.0", "description": "SignalR-based client for Stateflows framework", "main": "dist/index.js", "module": "./dist/index.mjs", @@ -26,7 +26,7 @@ "homepage": "https://www.stateflows.net", "dependencies": { "@microsoft/signalr": "^8.0.0", - "@stateflows/common": "file:../common" + "@stateflows/common": "^0.12.0" }, "devDependencies": { "tsup": "^8.0.1", diff --git a/Transport/Stateflows.Transport.Http/Stateflows.Transport.Http.csproj b/Transport/Stateflows.Transport.Http/Stateflows.Transport.Http.csproj index 2165dc4b..88f37d81 100644 --- a/Transport/Stateflows.Transport.Http/Stateflows.Transport.Http.csproj +++ b/Transport/Stateflows.Transport.Http/Stateflows.Transport.Http.csproj @@ -36,9 +36,4 @@ \ - - - - -