Skip to content

Commit 48fa517

Browse files
Merge pull request #3 from SimpleStateMachine/develop
Release 1.0
2 parents 6e464d3 + 4ac6ed2 commit 48fa517

19 files changed

+1242
-0
lines changed

SimpleStateMachineLibrary.sln

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.29806.167
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleStateMachineLibrary", "SimpleStateMachineLibrary\SimpleStateMachineLibrary.csproj", "{047A9390-803D-4964-B512-546D19B62066}"
77
EndProject
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{7EE69DED-8322-4467-89E3-692CC55F2503}"
9+
EndProject
810
Global
911
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1012
Debug|Any CPU = Debug|Any CPU
@@ -15,6 +17,10 @@ Global
1517
{047A9390-803D-4964-B512-546D19B62066}.Debug|Any CPU.Build.0 = Debug|Any CPU
1618
{047A9390-803D-4964-B512-546D19B62066}.Release|Any CPU.ActiveCfg = Release|Any CPU
1719
{047A9390-803D-4964-B512-546D19B62066}.Release|Any CPU.Build.0 = Release|Any CPU
20+
{7EE69DED-8322-4467-89E3-692CC55F2503}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21+
{7EE69DED-8322-4467-89E3-692CC55F2503}.Debug|Any CPU.Build.0 = Debug|Any CPU
22+
{7EE69DED-8322-4467-89E3-692CC55F2503}.Release|Any CPU.ActiveCfg = Release|Any CPU
23+
{7EE69DED-8322-4467-89E3-692CC55F2503}.Release|Any CPU.Build.0 = Release|Any CPU
1824
EndGlobalSection
1925
GlobalSection(SolutionProperties) = preSolution
2026
HideSolutionNode = FALSE
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using SimpleStateMachineLibrary.Helpers;
2+
3+
namespace SimpleStateMachineLibrary
4+
{
5+
public partial class Data : NamedObject
6+
{
7+
public object Value { get; set; }
8+
9+
public Data(StateMachine stateMachine, string nameData, object valueData = null) : base(stateMachine, nameData)
10+
{
11+
Value = valueData;
12+
}
13+
14+
public Data Delete()
15+
{
16+
return this.StateMachine.DeleteData(this);
17+
}
18+
19+
public Data TryDelete()
20+
{
21+
return this.StateMachine.TryDeleteData(this);
22+
}
23+
}
24+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using SimpleStateMachineLibrary.Helpers;
2+
using System.Xml.Linq;
3+
4+
5+
namespace SimpleStateMachineLibrary
6+
{
7+
public partial class Data
8+
{
9+
public static XElement ToXElement(Data data)
10+
{
11+
Check.NamedObject(data);
12+
XElement element = new XElement("Data");
13+
element.Add(new XAttribute("Name", data.Name));
14+
element.Add(new XAttribute("Value", data.Value.ToString()));
15+
return element;
16+
}
17+
18+
public XElement ToXElement()
19+
{
20+
XElement element = new XElement("Transition");
21+
element.Add(new XAttribute("Name", this.Name));
22+
element.Add(new XAttribute("Value", this.Value.ToString()));
23+
return element;
24+
}
25+
26+
public static Data FromXElement(StateMachine stateMachine, XElement data)
27+
{
28+
stateMachine = Check.Object(stateMachine);
29+
data = Check.Object(data);
30+
31+
string Name = data.Attribute("Name")?.Value;
32+
string Value = data.Attribute("Value")?.Value;
33+
return stateMachine.AddData(Name, Value);
34+
}
35+
}
36+
}
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace SimpleStateMachineLibrary.Helpers
5+
{
6+
public class Check
7+
{
8+
public static string Name(string name)
9+
{
10+
if (String.IsNullOrEmpty(name))
11+
throw new ArgumentNullException("Name must be not Empty");
12+
return name;
13+
}
14+
15+
public static TObject Object<TObject>(TObject objectRequested)
16+
{
17+
if (Equals(objectRequested, default(TObject)))
18+
throw new ArgumentNullException(String.Format("Object of type {0} must be not null", typeof(TObject).ToString()));
19+
return objectRequested;
20+
}
21+
22+
public static TObject NamedObject<TObject>(TObject objectRequested) where TObject : NamedObject
23+
{
24+
Check.Object(objectRequested);
25+
Check.Name(objectRequested.Name);
26+
return objectRequested;
27+
}
28+
29+
private static bool _Contains<TObject>(Dictionary<string, TObject> dictionary, string nameObject, bool needContains, bool exeption) where TObject : NamedObject
30+
{
31+
dictionary = Check.Object(dictionary);
32+
nameObject = Check.Name(nameObject);
33+
34+
if (needContains == dictionary.ContainsKey(nameObject))
35+
return true;
36+
if (exeption)
37+
if (needContains)
38+
throw new KeyNotFoundException(String.Format("Element with name {0} is not found", nameObject));
39+
else
40+
throw new ArgumentException(String.Format("Element with name {0} already exists", nameObject));
41+
return false;
42+
}
43+
44+
private static bool _Contains<TObject>(Dictionary<string, TObject> dictionary, TObject objectRequested, bool needContains, bool exeption) where TObject : NamedObject
45+
{
46+
dictionary = Check.Object(dictionary);
47+
objectRequested = Check.Object(objectRequested);
48+
49+
if (needContains == dictionary.ContainsValue(objectRequested))
50+
return true;
51+
52+
if (exeption)
53+
if (needContains)
54+
throw new KeyNotFoundException(String.Format("Element of type {0} not found", typeof(TObject).ToString()));
55+
else
56+
throw new ArgumentException(String.Format("Element of type {0} already exists", typeof(TObject).ToString()));
57+
return false;
58+
}
59+
60+
61+
public static bool Contains<TObject>(Dictionary<string, TObject> dictionary, string nameObject, bool exeption = true) where TObject : NamedObject
62+
{
63+
return _Contains(dictionary, nameObject, true, exeption);
64+
}
65+
66+
public static bool Contains<TObject>(Dictionary<string, TObject> dictionary, TObject objectRequested, bool exeption = true) where TObject : NamedObject
67+
{
68+
return _Contains(dictionary, objectRequested, true, exeption);
69+
}
70+
71+
72+
public static bool NotContains<TObject>(Dictionary<string, TObject> dictionary, string nameObject, bool exeption = true) where TObject : NamedObject
73+
{
74+
return _Contains(dictionary, nameObject, false, exeption);
75+
}
76+
77+
public static bool NotContains<TObject>(Dictionary<string, TObject> dictionary, TObject objectRequested, bool exeption = true) where TObject : NamedObject
78+
{
79+
return _Contains(dictionary, objectRequested, false, exeption);
80+
}
81+
82+
83+
public static TObject Remove<TObject>(Dictionary<string, TObject> dictionary, string nameObject, bool exeption = true) where TObject : NamedObject
84+
{
85+
dictionary = Check.Object(dictionary);
86+
nameObject = Check.Name(nameObject);
87+
88+
TObject removedObj = default(TObject);
89+
dictionary?.TryGetValue(nameObject, out removedObj);
90+
91+
if (removedObj == default(TObject))
92+
{
93+
if (exeption)
94+
throw new KeyNotFoundException(String.Format("Element with name {0} is not deleted because not found. ", nameObject));
95+
else
96+
return default(TObject);
97+
}
98+
99+
dictionary.Remove(nameObject);
100+
return removedObj;
101+
}
102+
103+
public static TObject Remove<TObject>(Dictionary<string, TObject> dictionary, TObject obj, bool exeption = true) where TObject : NamedObject
104+
{
105+
dictionary = Check.Object(dictionary);
106+
obj = Check.NamedObject(obj);
107+
108+
TObject removedObj = default(TObject);
109+
dictionary?.TryGetValue(obj.Name, out removedObj);
110+
111+
if (removedObj == default(TObject))
112+
{
113+
if (exeption)
114+
throw new KeyNotFoundException(String.Format("Element with name {0} is not deleted because not found. ", obj.Name));
115+
else
116+
return default(TObject);
117+
}
118+
119+
dictionary.Remove(obj.Name);
120+
return removedObj;
121+
}
122+
123+
124+
public static TObject GetElement<TObject>(Dictionary<string, TObject> dictionary, string nameObject, bool exeption = true) where TObject : NamedObject
125+
{
126+
bool contains = Contains(dictionary, nameObject, exeption);
127+
return contains ? dictionary[nameObject] : default(TObject);
128+
}
129+
130+
public static TObject GetElement<TObject>(Dictionary<string, TObject> dictionary, TObject obj, bool exeption = true) where TObject : NamedObject
131+
{
132+
bool contains = Contains(dictionary, obj, exeption);
133+
return contains ? obj : default(TObject);
134+
}
135+
136+
137+
public static TObject AddElement<TObject>(Dictionary<string, TObject> dictionary, TObject obj, bool exeption = true) where TObject : NamedObject
138+
{
139+
return AddElement(dictionary, obj?.Name, obj, exeption);
140+
}
141+
142+
public static TObject AddElement<TObject>(Dictionary<string, TObject> dictionary, string name, TObject obj, bool exeption = true) where TObject : NamedObject
143+
{
144+
obj = Check.NamedObject(obj);
145+
bool nonContains = NotContains(dictionary, name, exeption);
146+
147+
if (nonContains)
148+
return default(TObject);
149+
150+
dictionary.Add(name, obj);
151+
return obj;
152+
}
153+
}
154+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
namespace SimpleStateMachineLibrary.Helpers
2+
{
3+
4+
public abstract class NamedObject
5+
{
6+
public string Name { get; }
7+
public StateMachine StateMachine { get; }
8+
9+
public NamedObject(StateMachine stateMachine, string nameObject)
10+
{
11+
StateMachine = Check.Object(stateMachine);
12+
13+
Name = Check.Name(nameObject);
14+
}
15+
16+
}
17+
}
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
using System.Collections.Generic;
2+
using System.Xml.Linq;
3+
using System;
4+
using SimpleStateMachineLibrary.Helpers;
5+
6+
namespace SimpleStateMachineLibrary
7+
{
8+
public partial class StateMachine
9+
{
10+
private Dictionary<string, State> _states = new Dictionary<string, State>();
11+
12+
private Dictionary<string, Transition> _transitions = new Dictionary<string, Transition>();
13+
14+
private Dictionary<string, Data> _data = new Dictionary<string, Data>();
15+
16+
public State CurrentState { get; internal set; }
17+
18+
public Transition CurrentTransition{ get; internal set; }
19+
20+
public State StartState { get; protected set; }
21+
22+
public State EndState { get; protected set; }
23+
24+
public StateMachine()
25+
{
26+
27+
}
28+
29+
public StateMachine(XDocument xDocument)
30+
{
31+
FromXDocument(this, xDocument);
32+
}
33+
34+
public StateMachine(string xDocumentPath)
35+
{
36+
FromXDocument(this, xDocumentPath);
37+
}
38+
39+
40+
private Transition _nextTransition { get; set; }
41+
42+
private Dictionary<string, object> _currentParameters { get; set; }
43+
44+
private Dictionary<string, object> _nextParameters { get; set; }
45+
46+
47+
48+
private void CheckStartState()
49+
{
50+
if (StartState != null)
51+
{
52+
throw new ArgumentException(String.Format("Start state already set. It's {0} ", StartState.Name));
53+
}
54+
}
55+
56+
private void CheckEndState()
57+
{
58+
if (EndState != null)
59+
{
60+
throw new ArgumentException(String.Format("End state already set. It's {0} ", StartState.Name));
61+
}
62+
}
63+
64+
private void CheckCurrentTransition()
65+
{
66+
if (CurrentTransition == null)
67+
{
68+
throw new ArgumentException(String.Format("State with name \"{0}\" doesn't invoke transition", CurrentState.Name));
69+
}
70+
}
71+
72+
public State SetStartState(State state)
73+
{
74+
CheckStartState();
75+
StartState = State(Check.Object(state));
76+
return StartState;
77+
}
78+
79+
public State SetStartState(string stateName)
80+
{
81+
CheckEndState();
82+
StartState = State(Check.Object(stateName));
83+
return StartState;
84+
}
85+
86+
public State SetEndState(State state)
87+
{
88+
EndState = State(Check.Object(state));
89+
return EndState;
90+
}
91+
92+
public State SetEndState(string stateName)
93+
{
94+
EndState = State(Check.Object(stateName));
95+
return EndState;
96+
}
97+
98+
public void InvokeTransition(string nameTransition)
99+
{
100+
_nextTransition = Check.GetElement(_transitions, nameTransition, true);
101+
}
102+
103+
public void InvokeTransitionWithParameters(string nameTransition, Dictionary<string, object> parameters)
104+
{
105+
InvokeTransition(nameTransition);
106+
107+
_nextParameters = parameters;
108+
}
109+
110+
public void Start(Dictionary<string, object> startParameters = null)
111+
{
112+
CurrentState = StartState;
113+
CurrentState.Entry(startParameters);
114+
CurrentState.Exit(startParameters);
115+
while (CurrentState != EndState)
116+
{
117+
_currentParameters = _nextParameters;
118+
_nextParameters = null;
119+
120+
CurrentTransition = _nextTransition;
121+
_nextTransition = null;
122+
123+
CheckCurrentTransition();
124+
CurrentState = null;
125+
CurrentTransition.Invoke(_currentParameters);
126+
CurrentState = CurrentTransition.StateTo;
127+
CurrentTransition = null;
128+
129+
CurrentState.Entry(_currentParameters);
130+
CurrentState.Exit(_currentParameters);
131+
}
132+
133+
}
134+
135+
}
136+
}

0 commit comments

Comments
 (0)