using System;
using System.Collections.Generic;
using System.Text;
using log4net;
namespace TBF.BenchControl
{
public class State
{
///
/// DEBUG: all state changes and all operations
/// INFO: all state changes and operations that returned evnt != Event.None
/// WARN: 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()
{
ChangeState(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} returned {1}", operation, evnt);
events.Add(evnt);
}
else
{
log.DebugFormat("Operation {0} 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 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("ChangeState( {0} -> {1} )", previousState.ToString(), 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();
}
}
}
}
}