1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.statemachine;
21
22 import java.util.LinkedList;
23
24 import junit.framework.TestCase;
25
26 import org.apache.mina.statemachine.annotation.Transition;
27 import org.apache.mina.statemachine.annotation.Transitions;
28 import org.apache.mina.statemachine.event.Event;
29 import org.apache.mina.statemachine.transition.MethodTransition;
30
31
32
33
34
35
36
37 public class StateMachineProxyBuilderTest extends TestCase {
38
39 public void testReentrantStateMachine() throws Exception {
40 ReentrantStateMachineHandler handler = new ReentrantStateMachineHandler();
41
42 State s1 = new State("s1");
43 State s2 = new State("s2");
44 State s3 = new State("s3");
45
46 s1.addTransition(new MethodTransition("call1", s2, handler));
47 s2.addTransition(new MethodTransition("call2", s3, handler));
48 s3.addTransition(new MethodTransition("call3", handler));
49
50 StateMachine sm = new StateMachine(new State[] { s1, s2, s3 }, "s1");
51 Reentrant reentrant = new StateMachineProxyBuilder().create(Reentrant.class, sm);
52 reentrant.call1(reentrant);
53 assertTrue(handler.finished);
54 }
55
56 public void testTapeDeckStateMachine() throws Exception {
57 TapeDeckStateMachineHandler handler = new TapeDeckStateMachineHandler();
58
59 State parent = new State("parent");
60 State s1 = new State("s1", parent);
61 State s2 = new State("s2", parent);
62 State s3 = new State("s3", parent);
63 State s4 = new State("s4", parent);
64 State s5 = new State("s5", parent);
65
66 parent.addTransition(new MethodTransition("*", "error", handler));
67 s1.addTransition(new MethodTransition("insert", s2, "inserted", handler));
68 s2.addTransition(new MethodTransition("start", s3, "playing", handler));
69 s3.addTransition(new MethodTransition("stop", s4, "stopped", handler));
70 s3.addTransition(new MethodTransition("pause", s5, "paused", handler));
71 s4.addTransition(new MethodTransition("eject", s1, "ejected", handler));
72 s5.addTransition(new MethodTransition("pause", s3, "playing", handler));
73
74 StateMachine sm = new StateMachine(new State[] { s1, s2, s3, s4, s5 }, "s1");
75 TapeDeck player = new StateMachineProxyBuilder().create(TapeDeck.class, sm);
76 player.insert("Kings of convenience - Riot on an empty street");
77 player.start();
78 player.pause();
79 player.pause();
80 player.eject();
81 player.stop();
82 player.eject();
83
84 LinkedList<String> messages = handler.messages;
85 assertEquals("Tape 'Kings of convenience - Riot on an empty street' inserted", messages.removeFirst());
86 assertEquals("Playing", messages.removeFirst());
87 assertEquals("Paused", messages.removeFirst());
88 assertEquals("Playing", messages.removeFirst());
89 assertEquals("Error: Cannot eject at this time", messages.removeFirst());
90 assertEquals("Stopped", messages.removeFirst());
91 assertEquals("Tape ejected", messages.removeFirst());
92 assertTrue(messages.isEmpty());
93 }
94
95 public void testTapeDeckStateMachineAnnotations() throws Exception {
96 TapeDeckStateMachineHandler handler = new TapeDeckStateMachineHandler();
97
98 StateMachine sm = StateMachineFactory.getInstance(Transition.class).create(TapeDeckStateMachineHandler.S1, handler);
99
100 TapeDeck player = new StateMachineProxyBuilder().create(TapeDeck.class, sm);
101 player.insert("Kings of convenience - Riot on an empty street");
102 player.start();
103 player.pause();
104 player.pause();
105 player.eject();
106 player.stop();
107 player.eject();
108
109 LinkedList<String> messages = handler.messages;
110 assertEquals("Tape 'Kings of convenience - Riot on an empty street' inserted", messages.removeFirst());
111 assertEquals("Playing", messages.removeFirst());
112 assertEquals("Paused", messages.removeFirst());
113 assertEquals("Playing", messages.removeFirst());
114 assertEquals("Error: Cannot eject at this time", messages.removeFirst());
115 assertEquals("Stopped", messages.removeFirst());
116 assertEquals("Tape ejected", messages.removeFirst());
117 assertTrue(messages.isEmpty());
118 }
119
120 public interface Reentrant {
121 void call1(Reentrant proxy);
122 void call2(Reentrant proxy);
123 void call3(Reentrant proxy);
124 }
125
126 public static class ReentrantStateMachineHandler {
127 private boolean finished = false;
128
129 public void call1(Reentrant proxy) {
130 proxy.call2(proxy);
131 }
132
133 public void call2(Reentrant proxy) {
134 proxy.call3(proxy);
135 }
136
137 public void call3(
138 @SuppressWarnings("unused") Reentrant proxy) {
139 finished = true;
140 }
141 }
142
143 public interface TapeDeck {
144 void insert(String name);
145 void eject();
146 void start();
147 void pause();
148 void stop();
149 }
150
151 public static class TapeDeckStateMachineHandler {
152 @org.apache.mina.statemachine.annotation.State public static final String PARENT = "parent";
153 @org.apache.mina.statemachine.annotation.State(PARENT) public static final String S1 = "s1";
154 @org.apache.mina.statemachine.annotation.State(PARENT) public static final String S2 = "s2";
155 @org.apache.mina.statemachine.annotation.State(PARENT) public static final String S3 = "s3";
156 @org.apache.mina.statemachine.annotation.State(PARENT) public static final String S4 = "s4";
157 @org.apache.mina.statemachine.annotation.State(PARENT) public static final String S5 = "s5";
158
159 private LinkedList<String> messages = new LinkedList<String>();
160
161 @Transition(on = "insert", in = "s1", next = "s2")
162 public void inserted(String name) {
163 messages.add("Tape '" + name + "' inserted");
164 }
165
166 @Transition(on = "eject", in = "s4", next = "s1")
167 public void ejected() {
168 messages.add("Tape ejected");
169 }
170
171 @Transitions({@Transition( on = "start", in = "s2", next = "s3" ),
172 @Transition( on = "pause", in = "s5", next = "s3" )})
173 public void playing() {
174 messages.add("Playing");
175 }
176
177 @Transition(on = "pause", in = "s3", next = "s5")
178 public void paused() {
179 messages.add("Paused");
180 }
181
182 @Transition(on = "stop", in = "s3", next = "s4")
183 public void stopped() {
184 messages.add("Stopped");
185 }
186
187 @Transition(on = "*", in = "parent")
188 public void error(Event event) {
189 messages.add("Error: Cannot " + event.getId() + " at this time");
190 }
191 };
192 }