// Copyright (c) Microsoft Open Technologies, Inc. // All Rights Reserved // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING // WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF // TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR // NON-INFRINGEMENT. // See the Apache 2 License for the specific language governing // permissions and limitations under the License. namespace Microsoft.AspNet.Razor { public abstract class StateMachine { protected delegate StateResult State(); protected abstract State StartState { get; } protected State CurrentState { get; set; } protected virtual TReturn Turn() { if (CurrentState != null) { StateResult result; do { // Keep running until we get a null result or output result = CurrentState(); CurrentState = result.Next; } while (result != null && !result.HasOutput); if (result == null) { return default(TReturn); // Terminated } return result.Output; } return default(TReturn); } /// /// Returns a result indicating that the machine should stop executing and return null output. /// protected StateResult Stop() { return null; } /// /// Returns a result indicating that this state has no output and the machine should immediately invoke the specified state /// /// /// By returning no output, the state machine will invoke the next state immediately, before returning /// controller to the caller of /// protected StateResult Transition(State newState) { return new StateResult(newState); } /// /// Returns a result containing the specified output and indicating that the next call to /// should invoke the provided state. /// protected StateResult Transition(TReturn output, State newState) { return new StateResult(output, newState); } /// /// Returns a result indicating that this state has no output and the machine should remain in this state /// /// /// By returning no output, the state machine will re-invoke the current state again before returning /// controller to the caller of /// protected StateResult Stay() { return new StateResult(CurrentState); } /// /// Returns a result containing the specified output and indicating that the next call to /// should re-invoke the current state. /// protected StateResult Stay(TReturn output) { return new StateResult(output, CurrentState); } protected class StateResult { public StateResult(State next) { HasOutput = false; Next = next; } public StateResult(TReturn output, State next) { HasOutput = true; Output = output; Next = next; } public bool HasOutput { get; set; } public TReturn Output { get; set; } public State Next { get; set; } } } }