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