1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.xnap.util;
21
22 import java.util.HashSet;
23 import java.util.Hashtable;
24
25 import org.xnap.XNap;
26
27 public class FiniteStateMachine extends AbstractStateMachine
28 {
29
30
31
32
33
34
35
36 private Hashtable successorsByState;
37
38
39
40 public FiniteStateMachine(State initialState, Hashtable successorsByState)
41 {
42 super(initialState);
43
44 this.successorsByState = successorsByState;
45 }
46
47 public FiniteStateMachine(State initialState)
48 {
49 this(initialState, new Hashtable());
50 }
51
52
53
54 public synchronized void putState(State state, HashSet successors)
55 {
56 successorsByState.put(state, new HashSet(successors));
57 }
58
59 /***
60 */
61 protected synchronized void canChange(State oldState, State newState)
62 {
63 HashSet successors = (HashSet)successorsByState.get(oldState);
64 if (successors == null || !successors.contains(newState)) {
65 stateChangedFailed(oldState, newState);
66 }
67 }
68
69 /***
70 * Does nothing. Subclasses should overwrite this method.
71 */
72 protected synchronized void stateChanged(State oldState, State newState)
73 {
74 }
75
76 /***
77 * Throws an IllegalOperationException. Subclasses can
78 * overwrite this method.
79 *
80 * @exception IllegalOperationException thrown if the state transition
81 * is not valid */
82 protected synchronized void stateChangedFailed(State oldState,
83 State newState)
84 {
85
86 throw new IllegalOperationException
87 (XNap.tr("Operation not allowed: "
88 + oldState + " -> " + newState));
89 }
90
91
92
93 public static Hashtable createStateTable(State[][] table)
94 {
95 Hashtable stateTable = new Hashtable();
96
97 for (int i = 0; i < table.length; i++) {
98 HashSet set = new HashSet();
99 State[] row = table[i];
100 for (int j = 1; j < row.length; j++) {
101 set.add(row[j]);
102 }
103 stateTable.put(row[0], set);
104 }
105
106 return stateTable;
107 }
108
109 }