1 | package org.expeditee.core;
|
---|
2 |
|
---|
3 | import java.util.ArrayList;
|
---|
4 | import java.util.List;
|
---|
5 |
|
---|
6 | public class FSM {
|
---|
7 |
|
---|
8 | private int _currentState;
|
---|
9 | private List<Object> _transitions;
|
---|
10 | private List<Integer> _nextTrueStates;
|
---|
11 | private List<Integer> _nextFalseStates;
|
---|
12 | private List<Boolean> _finalStates;
|
---|
13 | private boolean _inconsistent;
|
---|
14 |
|
---|
15 | public FSM()
|
---|
16 | {
|
---|
17 | _transitions = new ArrayList<Object>();
|
---|
18 | _nextTrueStates = new ArrayList<Integer>();
|
---|
19 | _nextFalseStates = new ArrayList<Integer>();
|
---|
20 | _finalStates = new ArrayList<Boolean>();
|
---|
21 |
|
---|
22 | configureState(0, null, 0, 0, false);
|
---|
23 | reset();
|
---|
24 | }
|
---|
25 |
|
---|
26 | /**
|
---|
27 | * Resets the DFSM to its initial state.
|
---|
28 | */
|
---|
29 | public void reset()
|
---|
30 | {
|
---|
31 | _currentState = 0;
|
---|
32 | _inconsistent = false;
|
---|
33 | }
|
---|
34 |
|
---|
35 | /**
|
---|
36 | * Gets the current state of the DFSM.
|
---|
37 | */
|
---|
38 | public int currentState()
|
---|
39 | {
|
---|
40 | return _currentState;
|
---|
41 | }
|
---|
42 |
|
---|
43 | /**
|
---|
44 | * Whether the DFSM is in a consistent state. May be false if a state has been incorrectly
|
---|
45 | * configured causing a transition into unconfigured territory.
|
---|
46 | */
|
---|
47 | public boolean isConsistent()
|
---|
48 | {
|
---|
49 | return !_inconsistent;
|
---|
50 | }
|
---|
51 |
|
---|
52 | /**
|
---|
53 | * Edits the configuration of a given state.
|
---|
54 | *
|
---|
55 | * @param state The state to configure.
|
---|
56 | * @param transition The object to use for comparison to determine the next state.
|
---|
57 | * @param nextTrueState The next state to go to if the input is equal to the transition object.
|
---|
58 | * @param nextFalseState The next state to go to if the input is not equal to the transition object.
|
---|
59 | * @param isFinalState Whether this state is a final state.
|
---|
60 | */
|
---|
61 | public void configureState(int state, Object transition, int nextTrueState, int nextFalseState, boolean isFinalState)
|
---|
62 | {
|
---|
63 | if (state < 0 || nextTrueState < 0 || nextFalseState < 0) return;
|
---|
64 |
|
---|
65 | while (state > _transitions.size()) {
|
---|
66 | _transitions.add(null);
|
---|
67 | _nextTrueStates.add(null);
|
---|
68 | _nextFalseStates.add(null);
|
---|
69 | _finalStates.add(null);
|
---|
70 | }
|
---|
71 |
|
---|
72 | _transitions.set(state, transition);
|
---|
73 | _nextTrueStates.set(state, nextTrueState);
|
---|
74 | _nextFalseStates.set(state, nextFalseState);
|
---|
75 | _finalStates.set(state, isFinalState);
|
---|
76 | }
|
---|
77 |
|
---|
78 | /**
|
---|
79 | * Moves the DFSM to a new state based on comparing the input object to the transition
|
---|
80 | * object for the current state.
|
---|
81 | *
|
---|
82 | * @param input The input object to compare to.
|
---|
83 | */
|
---|
84 | public void input(Object input)
|
---|
85 | {
|
---|
86 | // Can't do anything if we are inconsistent
|
---|
87 | if (_inconsistent) return;
|
---|
88 |
|
---|
89 | // Get the transition object for the current state
|
---|
90 | Object transition = _transitions.get(_currentState);
|
---|
91 |
|
---|
92 | // Work out whether the input matches the transition object
|
---|
93 | boolean result;
|
---|
94 | if (transition == null) {
|
---|
95 | result = input == null;
|
---|
96 | } else {
|
---|
97 | result = transition.equals(input);
|
---|
98 | }
|
---|
99 |
|
---|
100 | // Work out which state to go to next
|
---|
101 | Integer nextState;
|
---|
102 | if (result) {
|
---|
103 | nextState = _nextTrueStates.get(_currentState);
|
---|
104 | } else {
|
---|
105 | nextState = _nextFalseStates.get(_currentState);
|
---|
106 | }
|
---|
107 |
|
---|
108 | // If there is no next state, we are inconsistent
|
---|
109 | if (nextState == null) {
|
---|
110 | _inconsistent = true;
|
---|
111 | return;
|
---|
112 | }
|
---|
113 |
|
---|
114 | // Go to the next state
|
---|
115 | _currentState = nextState;
|
---|
116 | }
|
---|
117 |
|
---|
118 | /**
|
---|
119 | * Whether or not this DFSM is currently in a final state.
|
---|
120 | */
|
---|
121 | public boolean isFinalState()
|
---|
122 | {
|
---|
123 | Boolean finalState = _finalStates.get(_currentState);
|
---|
124 | return !_inconsistent && finalState != null && finalState.booleanValue();
|
---|
125 | }
|
---|
126 |
|
---|
127 |
|
---|
128 | }
|
---|