252 lines
6.6 KiB
C#
252 lines
6.6 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: operation.Start(), operation.Stop()
|
|
/// INFO: operation.Run() when returned event != Event.None
|
|
/// WARN: EnterState() 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()
|
|
{
|
|
StopAndStartOperations(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}.Run() returned {1}", operation, evnt);
|
|
events.Add(evnt);
|
|
}
|
|
else
|
|
{
|
|
log.DebugFormat("Operation {0}.Run() 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 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();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|