tbf/TestBenchFramework/BenchControl/State.cs
2015-04-15 20:32:56 +02:00

258 lines
6.5 KiB
C#

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