private StateRepresentation EnterState(StateRepresentation representation, Transition transition, object [] args) { // Enter the new state representation.Enter(transition, args); if (FiringMode.Immediate.Equals(_firingMode) && !State.Equals(transition.Destination)) { // This can happen if triggers are fired in OnEntry // Must update current representation with updated State representation = GetRepresentation(State); transition = new Transition(transition.Source, State, transition.Trigger, args); } // Recursively enter substates that have an initial transition if (representation.HasInitialTransition) { // Verify that the target state is a substate // Check if state has substate(s), and if an initial transition(s) has been set up. if (!representation.GetSubstates().Any(s => s.UnderlyingState.Equals(representation.InitialTransitionTarget))) { throw new InvalidOperationException($"The target ({representation.InitialTransitionTarget}) for the initial transition is not a substate."); } var initialTransition = new InitialTransition(transition.Source, representation.InitialTransitionTarget, transition.Trigger, args); representation = GetRepresentation(representation.InitialTransitionTarget); representation = EnterState(representation, initialTransition, args); } return(representation); }
public static void InitialTransitionAddTransition(InitialTransition initialTransition, Transition transition) => initialTransition.AddTransition(transition);
async Task InternalFireOneAsync(TTrigger trigger, params object[] args) { // If this is a trigger with parameters, we must validate the parameter(s) if (_triggerConfiguration.TryGetValue(trigger, out var configuration)) { configuration.ValidateParameters(args); } var source = State; var representativeState = GetRepresentation(source); // Try to find a trigger handler, either in the current state or a super state. if (!representativeState.TryFindHandler(trigger, args, out var result)) { await _unhandledTriggerAction.ExecuteAsync(representativeState.UnderlyingState, trigger, result?.UnmetGuardConditions).ConfigureAwait(false); return; } // Check if this trigger should be ignored if (result.Handler is IgnoredTriggerBehaviour) { return; } // Handle special case, re-entry in superstate if (result.Handler is ReentryTriggerBehaviour handler) { // Handle transition, and set new state var transition = new Transition(source, handler.Destination, trigger, args); transition = await representativeState.ExitAsync(transition); State = transition.Destination; var newRepresentation = GetRepresentation(transition.Destination); if (!source.Equals(transition.Destination)) { // Then Exit the final superstate transition = new Transition(handler.Destination, handler.Destination, trigger, args); await newRepresentation.ExitAsync(transition); } await _onTransitionedEvent.InvokeAsync(new Transition(source, handler.Destination, trigger, args)); await newRepresentation.EnterAsync(transition, args); } // Check if it is an internal transition, or a transition from one state to another. else if (result.Handler.ResultsInTransitionFrom(source, args, out var destination)) { var transition = new Transition(source, destination, trigger, args); transition = await representativeState.ExitAsync(transition).ConfigureAwait(false); State = transition.Destination; var newRepresentation = GetRepresentation(transition.Destination); await newRepresentation.EnterAsync(transition, args); // Check if there is an intital transition configured if (newRepresentation.HasInitialTransition) { // Verify that the target state is a substate if (!newRepresentation.GetSubstates().Any(s => s.UnderlyingState.Equals(newRepresentation.InitialTransitionTarget))) { throw new InvalidOperationException($"The target ({newRepresentation.InitialTransitionTarget}) for the initial transition is not a substate."); } // Check if state has substate(s), and if an initial transition(s) has been set up. while (newRepresentation.GetSubstates().Any() && newRepresentation.HasInitialTransition) { var initialTransition = new InitialTransition(source, newRepresentation.InitialTransitionTarget, trigger, args); newRepresentation = GetRepresentation(newRepresentation.InitialTransitionTarget); await newRepresentation.EnterAsync(initialTransition, args); State = newRepresentation.UnderlyingState; } } // Alert all listeners of state transition await _onTransitionedEvent.InvokeAsync(new Transition(source, destination, trigger, args)); } else { var transition = new Transition(source, destination, trigger, args); await CurrentRepresentation.InternalActionAsync(transition, args).ConfigureAwait(false); } }
public static void StateNodeSetInitialTransition(PartialStateNode stateNode, InitialTransition initialTransition) => stateNode.Initial = Option.From <OneOf <InitialTransition, string> >(initialTransition);