using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; using System.Xml; namespace Anoto { /// /// This class implements a table-driven finite state machine. /// The table is defined by an XML document. The System.Xml.XmlTextReader /// class is used for fast scanning of the table and allows larger tables /// to be used as opposed to System.Xml.XmlDocument. /// class XMLStateMachine { private XmlTextReader tableParser; private string stateCurrent; private string stateTable; private string action; public XMLStateMachine() { tableParser = null; stateCurrent = String.Empty; stateTable = String.Empty; action = String.Empty; } /// /// The CurrentState property contains the current state in the table. /// public string CurrentState { get { return stateCurrent; } set { stateCurrent = value; } } /// /// The Action property contains a user-defined string /// that indicates an action to be performed on the current transition. /// public string Action { get { return action; } } /// /// The StateTable property contains the state table file name. /// public string StateTable { get { return stateTable; } set { stateTable = value; } } /// /// The Next method gets the next valid state given /// the current state and the supplied input. /// /// The input used to trigger a state transition. /// A string that identifies the next state public string Next(string inputArg) { string nextState = String.Empty; if (CurrentState != String.Empty) { try { tableParser = new XmlTextReader(StateTable); while (true == tableParser.Read()) { if (XmlNodeType.Element == tableParser.NodeType) { if (true == tableParser.HasAttributes) { string state = tableParser.GetAttribute("name"); if (state == CurrentState) { // Get transition data while (true == tableParser.Read()) { if ((XmlNodeType.Element == tableParser.NodeType) && ("transition" == tableParser.Name)) { if (true == tableParser.HasAttributes) { string input = tableParser.GetAttribute("input"); if (input == inputArg) { CurrentState = tableParser.GetAttribute("next"); nextState = CurrentState; action = tableParser.GetAttribute("action"); return nextState; } } } } } } } } } catch (XmlException e) { // Eliminate default trace listener Trace.Listeners.RemoveAt(0); // Add console trace listener TextWriterTraceListener myWriter = new TextWriterTraceListener(System.Console.Out); Trace.Listeners.Add(myWriter); Trace.WriteLine("[XMLStateMachine] Could not load state table definition."); Trace.Indent(); Trace.WriteLine(e.Message); Trace.Unindent(); // Clean up object tableParser.Close(); tableParser = null; stateCurrent = String.Empty; action = String.Empty; } } return nextState; } } }