summaryrefslogtreecommitdiff
path: root/Anoto/StateMachine.cs
blob: 488376d6ba0efd01315093b771d25d4efd940c5c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Xml;

namespace Anoto
{

    /// <remarks>
    /// 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.
    /// </remarks>
    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;
        }

        /// <summary>
        /// The CurrentState property contains the current state in the table.
        /// </summary>
        public string CurrentState
        {
            get
            {
                return stateCurrent;
            }
            set
            {
                stateCurrent = value;
            }
        }

        /// <summary>
        /// The Action property contains a user-defined string
        /// that indicates an action to be performed on the current transition.
        /// </summary>
        public string Action
        {
            get
            {
                return action;
            }
        }

        /// <summary>
        /// The StateTable property contains the state table file name.
        /// </summary>
        public string StateTable
        {
            get
            {
                return stateTable;
            }
            set
            {
                stateTable = value;
            }
        }

        /// <summary>
        /// The Next method gets the next valid state given
        /// the current state and the supplied input.
        /// </summary>
        /// <param name="inputArg">The input used to trigger a state transition.</param>
        /// <returns>A string that identifies the next state</returns>
        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;
        }

      




    }
}