/// /// Copyright (c) 2013-2015 Sensus Metering Systems /// using System; using System.Collections.Generic; using System.Text; using log4net; namespace TBF.BenchControl { public class State { /// /// DEBUG: operation.Start(), operation.Stop() /// INFO: operation.Run() when returned event != Event.None /// WARN: EnterState() only state changes /// private static readonly ILog log = LogManager.GetLogger(typeof(State)); public override string ToString() { return Name + (Label==null ? "" : ", label=" + Label); } /// Current state (static) public static State CurrentState { get { return currentState; } } static State currentState; /// /// Events returned by the last RunOperations() /// public static IList LastEvents; /// State with an empty list of operations /// Useful when entering the first state and leaving the last one public static State Empty { get { return new State("empty"); } } /// /// Static constructor that initializes CurrentState /// static State() { PermanentOperations = new List(); currentState = State.Empty; } /// /// Instance fields set or initialized by the constructor /// public static IList PermanentOperations; public readonly IList Operations; public readonly IList Transitions; public readonly string Name; public readonly string Label; /// /// Constructor with a label /// public State(string name, string label) { this.Name = name; this.Label = label; Operations = new List(); foreach (var op in PermanentOperations) Operations.Add(op); Transitions = new List(); log.Debug(this.ToString()); } /// /// Default constructor /// public State(string name) : this(name, null) { } /// /// Create a new state without a label /// public static State Create(string name) { return new State(name); } /// /// Create a new state with a label /// public static State Create(string name, string label) { return new State(name, label); } /// /// Add an operation to the list of permanent opertion (and to this state) /// /// operation public State AddPermanentOperation(IOperation operation) { if (operation != null) { Operations.Add(operation); PermanentOperations.Add(operation); } return this; } /// /// Remove an operation from the list of permanent opertion (and from this state) /// /// operation public State RemovePermanentOperation(IOperation operation) { if (operation != null) { Operations.Remove(operation); PermanentOperations.Remove(operation); } return this; } /// /// Remove all permanent operations from this state and from the list /// (= clear the list of permanent operations) /// /// operation public State RemoveAllPermanentOperations() { if (PermanentOperations != null) { foreach (var op in PermanentOperations) Operations.Remove(op); PermanentOperations.Clear(); } return this; } /// /// Add an operation to this state /// /// operation public State AddOperation(IOperation operation) { if (operation != null) Operations.Add(operation); return this; } /// /// Add a list of operations to this state /// /// operation public State AddOperations(IList operations) { if (operations != null) { foreach (var op in operations) { if (op != null) Operations.Add(op); } } return this; } /// /// Add a state transition to the state /// /// transition public State AddTransition(Transition transition) { if (transition != null) Transitions.Add(transition); return this; } /// /// Enter a new state /// public State EnterState() { StopAndStartOperations(State.currentState, this); State.currentState = this; UiBridge.Bridge.OnStateChanged(this, State.currentState.ToString()); return this; } // ----------------------------------- Run time ----------------------------------------- /// /// Execute Run() methods of all operations of the current state. /// /// List of Event-s returned from the state operations public static IList RunOperations() { IList events = new List(); foreach (IOperation operation in currentState.Operations) { Event evnt = operation.Run(); if (evnt != Event.None) { log.InfoFormat("Operation {0}.Run() returned {1}", operation, evnt); events.Add(evnt); } else { log.DebugFormat("Operation {0}.Run() returned {1}", operation, evnt); } } LastEvents = events; return events; } /// /// Execute Stop() methods of all operations of the current state. /// public static void StopOperations() { foreach (IOperation operation in currentState.Operations) { log.DebugFormat("stopping {0}", operation); operation.Stop(); } } /// /// Run Stop() and Start() methods of operations when changing the state. /// /// Stopping state /// Starting state static void StopAndStartOperations(State previousState, State newState) { /// Stop() the previous state operations, which are not in the next state foreach (IOperation operation in previousState.Operations) { if (!newState.Operations.Contains(operation)) { log.DebugFormat("stopping {0}", operation); operation.Stop(); } } log.WarnFormat("---------------( {0} )---------------", newState.ToString()); /// Start() the operations that are in the current (new) state, but aren't in the previous state. foreach (IOperation operation in newState.Operations) { if (!previousState.Operations.Contains(operation)) { log.DebugFormat("starting {0}", operation); operation.Start(); } } } } }