예제 #1
0
 /// <summary>
 /// Removes the transition.
 /// </summary>
 /// <param name="transition">The transition.</param>
 public virtual void RemoveTransition(IFiniteStateTransition transition)
 {
     if (this.registeredTransitions.Contains(transition))
     {
         this.registeredTransitions.Remove(transition);
     }
 }
		/// <summary>
		/// Initializes a new instance of the <see cref="DuplicateTransitionCodeException"/> class.
		/// </summary>
		/// <param name="transition">The transition.</param>
		/// <param name="innerException">The inner exception.</param>
		public DuplicateTransitionCodeException(IFiniteStateTransition transition, Exception innerException)
			: base(
				string.Format(
					CultureInfo.CurrentCulture, "The {0} transition's Code value is already in use.", transition.Name),
				innerException)
		{
		}
 /// <summary>
 /// Initializes a new instance of the <see cref="DuplicateTransitionCodeException"/> class.
 /// </summary>
 /// <param name="transition">The transition.</param>
 /// <param name="innerException">The inner exception.</param>
 public DuplicateTransitionCodeException(IFiniteStateTransition transition, Exception innerException)
     : base(
         string.Format(
             CultureInfo.CurrentCulture, "The {0} transition's Code value is already in use.", transition.Name),
         innerException)
 {
 }
		/// <summary>
		/// Initializes a new instance of the <see cref="TransitionAlreadyRegisteredException"/> class.
		/// </summary>
		/// <param name="state">The state.</param>
		/// <param name="transition">The transition.</param>
		/// <param name="innerException">The inner exception.</param>
		public TransitionAlreadyRegisteredException(IFiniteState state, IFiniteStateTransition transition, Exception innerException)
			: base(
				string.Format(
					CultureInfo.CurrentCulture, "The {0} state is already registered with the {1} transition.", state.Name, transition.Name),
				innerException)
		{
		}
 /// <summary>
 /// Initializes a new instance of the <see cref="TransitionAlreadyRegisteredException"/> class.
 /// </summary>
 /// <param name="state">The state.</param>
 /// <param name="transition">The transition.</param>
 /// <param name="innerException">The inner exception.</param>
 public TransitionAlreadyRegisteredException(IFiniteState state, IFiniteStateTransition transition, Exception innerException)
     : base(
         string.Format(
             CultureInfo.CurrentCulture, "The {0} state is already registered with the {1} transition.", state.Name, transition.Name),
         innerException)
 {
 }
		/// <summary>
		/// Initializes a new instance of the <see cref="StateNotRegisteredException"/> class.
		/// </summary>
		/// <param name="transition">
		/// The transition.
		/// </param>
		/// <param name="state">
		/// The state.
		/// </param>
		/// <param name="innerException">
		/// The inner exception.
		/// </param>
		public StateNotRegisteredException(
			IFiniteStateTransition transition, IFiniteState state, Exception innerException)
			: base(
				string.Format(
					CultureInfo.CurrentCulture, "The {0} transition returned an unregistered {1} state.", transition.Name, state.Name),
				innerException)
		{
		}
		/// <summary>
		/// Initializes a new instance of the <see cref="TransitionNotAvailableException"/> class.
		/// </summary>
		/// <param name="transition">
		/// The transition.
		/// </param>
		/// <param name="state">
		/// The state.
		/// </param>
		/// <param name="innerException">
		/// The inner exception.
		/// </param>
		public TransitionNotAvailableException(
			IFiniteStateTransition transition, IFiniteState state, Exception innerException)
			: base(
				string.Format(
					CultureInfo.CurrentCulture, "The {0} transition is not available in the {1} state.", transition.Name, state.Name),
				innerException)
		{
		}
예제 #8
0
 /// <summary>
 /// Initializes a new instance of the <see cref="TransitionNotAvailableException"/> class.
 /// </summary>
 /// <param name="transition">
 /// The transition.
 /// </param>
 /// <param name="state">
 /// The state.
 /// </param>
 /// <param name="innerException">
 /// The inner exception.
 /// </param>
 public TransitionNotAvailableException(
     IFiniteStateTransition transition, IFiniteState state, Exception innerException)
     : base(
         string.Format(
             CultureInfo.CurrentCulture, "The {0} transition is not available in the {1} state.", transition.Name, state.Name),
         innerException)
 {
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="StateNotRegisteredException"/> class.
 /// </summary>
 /// <param name="transition">
 /// The transition.
 /// </param>
 /// <param name="state">
 /// The state.
 /// </param>
 /// <param name="innerException">
 /// The inner exception.
 /// </param>
 public StateNotRegisteredException(
     IFiniteStateTransition transition, IFiniteState state, Exception innerException)
     : base(
         string.Format(
             CultureInfo.CurrentCulture, "The {0} transition returned an unregistered {1} state.", transition.Name, state.Name),
         innerException)
 {
 }
예제 #10
0
        /// <summary>
        /// Initializes a new instance of the <see cref="FiniteStateMachine{THistoryEntry}" /> class.
        /// Initializes a new instance of the <see cref="FiniteStateMachine&lt;THistoryEntry&gt;" /> class.
        /// </summary>
        /// <param name="startingTransition">The starting transition.</param>
        protected FiniteStateMachine(IFiniteStateTransition startingTransition)
        {
            this.History = new FiniteStateMachineHistory <THistoryEntry>();

            this.StartingTransition = startingTransition;

            this.StartingState = this.StartingTransition.EndState;

            this.Initialize();
        }
예제 #11
0
        /// <summary>
        /// Tries the state of the get transition in any.
        /// </summary>
        /// <typeparam name="T">The type of transition to find</typeparam>
        /// <param name="transition">The transition.</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
        public virtual bool TryGetTransitionInAnyState <T>(out IFiniteStateTransition transition) where T : IFiniteStateTransition
        {
            foreach (var finiteState in this.States)
            {
                if (this.TryGetTransitionInState <T>(finiteState, out transition))
                {
                    return(true);
                }
            }

            transition = null;
            return(false);
        }
예제 #12
0
        /// <summary>
        /// Tries the name of the get transition in any state by.
        /// </summary>
        /// <param name="transitionName">Name of the transition.</param>
        /// <param name="transition">The transition.</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
        public virtual bool TryGetTransitionInAnyStateByName(string transitionName, out IFiniteStateTransition transition)
        {
            foreach (var finiteState in this.States)
            {
                transition = finiteState.GetTransitionByName(transitionName);
                if (transition != null)
                {
                    return(true);
                }
            }

            transition = null;
            return(false);
        }
예제 #13
0
        /// <summary>
        /// Registers a transition.
        /// </summary>
        /// <param name="transition">The transition.</param>
        public virtual void RegisterTransition(IFiniteStateTransition transition)
        {
            if (this.registeredTransitions.Contains(transition))
            {
                throw new TransitionAlreadyRegisteredException(this, transition);
            }

            // If it's not the same transition, but the Code value is already in use then throw...
            if (this.registeredTransitions.Any(x => x.Code == transition.Code))
            {
                throw new DuplicateTransitionCodeException(transition);
            }

            this.registeredTransitions.Add(transition);
        }
        public void NotChangeStateGivenTransitionCanTransitionDelegateReturnsFalse()
        {
            // Arrange
            this.openState.RemoveTransition(this.closeTransition);

            this.closeTransition = new FiniteStateTransition(
                2,
                "Close",
                new FiniteStateMachineTransitionReason("2", "Closed"),
                this.closedState,
                () => this.closedState,
                () => false);

            this.openState.RegisterTransition(this.closeTransition);

            // Act & Assert
            Assert.Throws <ApplicationException>(() => this.machine.PerformTransition(this.closeTransition));
        }
예제 #15
0
        /// <summary>
        /// Initializes the garage door state machine.
        /// </summary>
        private void InitializeStateMachine()
        {
            // Create the garage door states...
            this.openState   = new FiniteState((int)GarageDoorState.Open, "Open");
            this.closedState = new FiniteState((int)GarageDoorState.Closed, "Closed");

            // Create the garage door transitions...
            this.openTransition = new FiniteStateTransition(
                (int)GarageDoorTransition.Open,
                "Open",
                new FiniteStateMachineTransitionReason("Opened"),
                this.openState,
                () => this.openState,
                () => this.CanOpen);

            this.lockTransition = new FiniteStateTransition(
                (int)GarageDoorTransition.Lock,
                "Lock",
                new FiniteStateMachineTransitionReason("Closed and Locked"),
                this.closedState,
                () => this.closedState,
                () => this.CanLock);

            this.closeTransition = new FiniteStateTransition(
                (int)GarageDoorTransition.Close,
                "Close",
                new FiniteStateMachineTransitionReason("Closed"),
                this.closedState,
                () => this.closedState,
                () => this.CanClose);

            // Register the garage door transitions with their respective garage door states...
            this.openState.RegisterTransition(this.closeTransition);
            this.openState.RegisterTransition(this.lockTransition);
            this.closedState.RegisterTransition(this.openTransition);
            this.closedState.RegisterTransition(this.lockTransition);

            // Create the garage door state machine...
            this.stateMachine = new FiniteStateMachine.FiniteStateMachine(this.openState);

            // Register the garage door states with the garage door state machine...
            this.stateMachine.RegisterState(this.openState);
            this.stateMachine.RegisterState(this.closedState);
        }
		public void TestSetup()
		{
			// Create our states...
			this.openState = new FiniteState(0, "Open");
			this.closedState = new FiniteState(1, "Closed");

			// Create our transitions...
			this.startTransition = new FiniteStateTransition(0, "New", new FiniteStateMachineTransitionReason("0", "New"), this.openState);

			this.openTransition = new FiniteStateTransition(1, "Open", new FiniteStateMachineTransitionReason("1", "Opened"), this.closedState, this.openState);
			this.closeTransition = new FiniteStateTransition(2, "Close", new FiniteStateMachineTransitionReason("2", "Closed"), this.openState, this.closedState);

			// Add our transitions to our states...
			this.openState.RegisterTransition(this.closeTransition);
			this.closedState.RegisterTransition(this.openTransition);

			// Create our machine...
			this.machine = new FiniteStateMachine.FiniteStateMachine(this.startTransition);
		}
        public void ThrowExceptionGivenTransitionReturnsUnregisteredState()
        {
            // Arrange
            var unregisteredState = new FiniteState(99, "Unregistered");

            this.openState.RemoveTransition(this.closeTransition);

            this.closeTransition = new FiniteStateTransition(
                2,
                "Close",
                new FiniteStateMachineTransitionReason("2", "Closed"),
                unregisteredState,
                () => unregisteredState);

            this.openState.RegisterTransition(this.closeTransition);

            // Act
            Assert.Throws <StateNotRegisteredException>(() => this.machine.PerformTransition(this.closeTransition));
        }
예제 #18
0
        public void TestSetup()
        {
            // Create our states...
            this.openState   = new FiniteState(0, "Open");
            this.closedState = new FiniteState(1, "Closed");

            // Create our transitions...
            this.startTransition = new FiniteStateTransition(0, "New", new FiniteStateMachineTransitionReason("0", "New"), this.openState);

            this.openTransition  = new FiniteStateTransition(1, "Open", new FiniteStateMachineTransitionReason("1", "Opened"), this.closedState, this.openState);
            this.closeTransition = new FiniteStateTransition(2, "Close", new FiniteStateMachineTransitionReason("2", "Closed"), this.openState, this.closedState);

            // Add our transitions to our states...
            this.openState.RegisterTransition(this.closeTransition);
            this.closedState.RegisterTransition(this.openTransition);

            // Create our machine...
            this.machine = new FiniteStateMachine.FiniteStateMachine(this.startTransition);
        }
        public void ChangeCurrentStateGivenTransitionWithDelegate()
        {
            // Arrange
            this.openState.RemoveTransition(this.closeTransition);

            this.closeTransition = new FiniteStateTransition(
                2,
                "Close",
                new FiniteStateMachineTransitionReason("2", "Closed"),
                this.closedState,
                () => this.closedState);

            this.openState.RegisterTransition(this.closeTransition);

            // Act
            this.machine.PerformTransition(this.closeTransition);

            // Assert
            Assert.IsTrue(this.machine.CurrentState.Name.Equals("Closed"));
        }
		public void ThrowExceptionGivenTransitionReturnsUnregisteredState()
		{
			// Arrange
			var unregisteredState = new FiniteState(0, "Unregistered");

			this.openState.RemoveTransition(this.closeTransition);

			this.closeTransition = new FiniteStateTransition(
				2,
				"Close",
				new FiniteStateMachineTransitionReason("2", "Closed"),
				unregisteredState,
				() => unregisteredState);

			this.openState.RegisterTransition(this.closeTransition);

			// Act
			this.machine.PerformTransition(this.closeTransition);
		}
예제 #21
0
        /// <summary>
        /// Determines if a transition requires transition data.
        /// </summary>
        /// <param name="transition">The transition.</param>
        /// <returns>True if the transition requires transition data. False otherwise.</returns>
        private static bool TransitionRequiresTransitionData(IFiniteStateTransition transition)
        {
            var requiresTransitionData = transition.GetType().GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IFiniteStateTransition <>));

            return(requiresTransitionData);
        }
예제 #22
0
 /// <summary>
 /// Tries the state of the get transition in.
 /// </summary>
 /// <typeparam name="T">The type of transition to find</typeparam>
 /// <param name="state">The state.</param>
 /// <param name="transition">The transition.</param>
 /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
 protected virtual bool TryGetTransitionInState <T>(IFiniteState state, out IFiniteStateTransition transition) where T : IFiniteStateTransition
 {
     transition = state.Transitions.OfType <T>().FirstOrDefault();
     return(transition != null);
 }
예제 #23
0
 /// <summary>
 /// Transitions to a new state.
 /// </summary>
 /// <param name="transition">The transition.</param>
 /// <returns>The resulting state.</returns>
 protected virtual IFiniteState Transition(IFiniteStateTransition transition)
 {
     throw new ApplicationException("This finite state machine has one or more transitions that require transition data. You must override Transition() in your implementation.");
 }
예제 #24
0
 /// <summary>
 /// Tries the name of the get transition in current state by.
 /// </summary>
 /// <param name="transitionName">Name of the transition.</param>
 /// <param name="transition">The transition.</param>
 /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
 public virtual bool TryGetTransitionInCurrentStateByName(string transitionName, out IFiniteStateTransition transition)
 {
     transition = this.CurrentState.GetTransitionByName(transitionName);
     return(transition != null);
 }
예제 #25
0
 /// <summary>
 /// Adds the history entry.
 /// </summary>
 /// <param name="transition">The transition.</param>
 /// <param name="transitionResult">The transition result.</param>
 /// <param name="comments">The comments.</param>
 /// <returns>A built-up history entry.</returns>
 protected abstract THistoryEntry BuildHistoryEntry(IFiniteStateTransition transition, IFiniteState transitionResult, string comments);
예제 #26
0
		/// <summary>
		/// Initializes the garage door state machine.
		/// </summary>
		private void InitializeStateMachine()
		{
			// Create the garage door states...
			this.openState = new FiniteState((int)GarageDoorState.Open, "Open");
			this.closedState = new FiniteState((int)GarageDoorState.Closed, "Closed");

			// Create the garage door transitions...
			this.openTransition = new FiniteStateTransition(
				(int)GarageDoorTransition.Open,
				"Open",
				new FiniteStateMachineTransitionReason("Opened"),
				this.openState,
				() => this.openState,
				() => this.CanOpen);

			this.lockTransition = new FiniteStateTransition(
				(int)GarageDoorTransition.Lock,
				"Lock",
				new FiniteStateMachineTransitionReason("Closed and Locked"),
				this.closedState,
				() => this.closedState,
				() => this.CanLock);

			this.closeTransition = new FiniteStateTransition(
				(int)GarageDoorTransition.Close,
				"Close",
				new FiniteStateMachineTransitionReason("Closed"),
				this.closedState,
				() => this.closedState,
				() => this.CanClose);

			// Register the garage door transitions with their respective garage door states...
			this.openState.RegisterTransition(this.closeTransition);
			this.openState.RegisterTransition(this.lockTransition);
			this.closedState.RegisterTransition(this.openTransition);
			this.closedState.RegisterTransition(this.lockTransition);

			// Create the garage door state machine...
			this.stateMachine = new FiniteStateMachine.FiniteStateMachine(this.openState);

			// Register the garage door states with the garage door state machine...
			this.stateMachine.RegisterState(this.openState);
			this.stateMachine.RegisterState(this.closedState);
		}
예제 #27
0
 /// <summary>
 /// Tries to get the IFiniteStateTransition by type in the current state.
 /// </summary>
 /// <typeparam name="T">The type of transition</typeparam>
 /// <param name="transition">The transition.</param>
 /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
 public virtual bool TryGetTransitionInCurrentState <T>(out IFiniteStateTransition transition) where T : IFiniteStateTransition
 {
     return(this.TryGetTransitionInState <T>(this.CurrentState, out transition));
 }
예제 #28
0
 /// <summary>
 /// Initializes a new instance of the <see cref="StateChangedEventArgs"/> class.
 /// </summary>
 /// <param name="transition">The transition.</param>
 /// <param name="transitionResult">The transition result.</param>
 /// <param name="comment">The comment.</param>
 public StateChangedEventArgs(IFiniteStateTransition transition, IFiniteState transitionResult, string comment = null)
 {
     this.Transition       = transition;
     this.TransitionResult = transitionResult;
     this.Comment          = comment;
 }
예제 #29
0
        /// <summary>
        /// Performs the transition.
        /// </summary>
        /// <param name="transition">The transition.</param>
        /// <param name="comment">The comment.</param>
        public virtual void PerformTransition(IFiniteStateTransition transition, string comment = null)
        {
            Guard.Will.ProtectAgainstNullArgument(() => transition);

            // If the requested transition is not available then...
            var hasTransition = this.CurrentState.Transitions.FirstOrDefault(x => x.Code == transition.Code) != null;

            if (!hasTransition)
            {
                throw new TransitionNotAvailableException(transition, this.CurrentState);
            }

            Guard.Will.ThrowException("The transition does not have an end state.").When(transition.EndState.IsNull());

            IFiniteState transitionResult;

            // If the transition requires data then call our virtual members (the implementer MUST override), otherwise just do business as usual...
            if (TransitionRequiresTransitionData(transition))
            {
                if (!this.CanTransition(transition))
                {
                    throw new ApplicationException("The transition cannot be executed.");
                }

                transitionResult = this.Transition(transition);
            }
            else
            {
                if (!transition.CanTransition())
                {
                    throw new ApplicationException("The transition cannot be executed.");
                }

                transitionResult = transition.Transition();
            }

            // If the transition failed then pop...
            if (!transition.TransitionSucceeded)
            {
                if (string.IsNullOrEmpty(transition.FailureMessage))
                {
                    throw new ApplicationException("The transition failed. No failure message was provided by the transition.");
                }

                throw new ApplicationException(transition.FailureMessage.FormattedWith("The transition failed. {0}"));
            }

            // If the transition returned a state that isn't in our list of states then...
            if (!this.States.Contains(transitionResult))
            {
                throw new StateNotRegisteredException(transition, transitionResult);
            }

            // Write the transition to the history...
            var historyEntry = this.BuildHistoryEntry(transition, transitionResult, comment);

            this.History.AddEntry(historyEntry);

            // Raise the state changed event...
            this.OnStateChanged(new StateChangedEventArgs(transition, transitionResult, comment));
        }
예제 #30
0
 /// <summary>
 /// Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object.
 /// </summary>
 /// <param name="transition">A transition to compare with this instance.</param>
 /// <returns>A value that indicates the relative order of the objects being compared. The return value has these meanings: Value Meaning Less than zero This instance is less than <paramref name="transition" />. Zero This instance is equal to <paramref name="transition" />. Greater than zero This instance is greater than <paramref name="transition" />.</returns>
 public int CompareTo(IFiniteStateTransition transition)
 {
     return(this.Code.CompareTo(transition.Code));
 }
		/// <summary>
		/// Initializes a new instance of the <see cref="StateChangedEventArgs"/> class.
		/// </summary>
		/// <param name="transition">The transition.</param>
		/// <param name="transitionResult">The transition result.</param>
		/// <param name="comment">The comment.</param>
		public StateChangedEventArgs(IFiniteStateTransition transition, IFiniteState transitionResult, string comment = null)
		{
			this.Transition = transition;
			this.TransitionResult = transitionResult;
			this.Comment = comment;
		}
		public void ChangeCurrentStateGivenTransitionWithDelegate()
		{
			// Arrange
			this.openState.RemoveTransition(this.closeTransition);

			this.closeTransition = new FiniteStateTransition(
				2,
				"Close",
				new FiniteStateMachineTransitionReason("2", "Closed"),
				this.closedState,
				() => this.closedState);

			this.openState.RegisterTransition(this.closeTransition);

			// Act
			this.machine.PerformTransition(this.closeTransition);

			// Assert
			Assert.IsTrue(this.machine.CurrentState.Name.Equals("Closed"));
		}