View Javadoc

1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.mina.statemachine;
21  
22  import static org.junit.Assert.assertEquals;
23  import static org.junit.Assert.assertTrue;
24  
25  import java.util.LinkedList;
26  
27  import org.apache.mina.statemachine.annotation.Transition;
28  import org.apache.mina.statemachine.annotation.Transitions;
29  import org.apache.mina.statemachine.event.Event;
30  import org.apache.mina.statemachine.transition.MethodTransition;
31  import org.junit.Test;
32  
33  /**
34   * Tests {@link StateMachineProxyBuilder}.
35   *
36   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
37   */
38  public class StateMachineProxyBuilderTest {
39      @Test
40      public void testReentrantStateMachine() throws Exception {
41          ReentrantStateMachineHandler handler = new ReentrantStateMachineHandler();
42  
43          State s1 = new State("s1");
44          State s2 = new State("s2");
45          State s3 = new State("s3");
46  
47          s1.addTransition(new MethodTransition("call1", s2, handler));
48          s2.addTransition(new MethodTransition("call2", s3, handler));
49          s3.addTransition(new MethodTransition("call3", handler));
50  
51          StateMachine sm = new StateMachine(new State[] { s1, s2, s3 }, "s1");
52          Reentrant reentrant = new StateMachineProxyBuilder().create(Reentrant.class, sm);
53          reentrant.call1(reentrant);
54          assertTrue(handler.finished);
55      }
56      
57      @Test
58      public void testTapeDeckStateMachine() throws Exception {
59          TapeDeckStateMachineHandler handler = new TapeDeckStateMachineHandler();
60  
61          State parent = new State("parent");
62          State s1 = new State("s1", parent);
63          State s2 = new State("s2", parent);
64          State s3 = new State("s3", parent);
65          State s4 = new State("s4", parent);
66          State s5 = new State("s5", parent);
67  
68          parent.addTransition(new MethodTransition("*", "error", handler));
69          s1.addTransition(new MethodTransition("insert", s2, "inserted", handler));
70          s2.addTransition(new MethodTransition("start", s3, "playing", handler));
71          s3.addTransition(new MethodTransition("stop", s4, "stopped", handler));
72          s3.addTransition(new MethodTransition("pause", s5, "paused", handler));
73          s4.addTransition(new MethodTransition("eject", s1, "ejected", handler));
74          s5.addTransition(new MethodTransition("pause", s3, "playing", handler));
75  
76          StateMachine sm = new StateMachine(new State[] { s1, s2, s3, s4, s5 }, "s1");
77          TapeDeck player = new StateMachineProxyBuilder().create(TapeDeck.class, sm);
78          player.insert("Kings of convenience - Riot on an empty street");
79          player.start();
80          player.pause();
81          player.pause();
82          player.eject();
83          player.stop();
84          player.eject();
85  
86          LinkedList<String> messages = handler.messages;
87          assertEquals("Tape 'Kings of convenience - Riot on an empty street' inserted", messages.removeFirst());
88          assertEquals("Playing", messages.removeFirst());
89          assertEquals("Paused", messages.removeFirst());
90          assertEquals("Playing", messages.removeFirst());
91          assertEquals("Error: Cannot eject at this time", messages.removeFirst());
92          assertEquals("Stopped", messages.removeFirst());
93          assertEquals("Tape ejected", messages.removeFirst());
94          assertTrue(messages.isEmpty());
95      }
96      
97      @Test
98      public void testTapeDeckStateMachineAnnotations() throws Exception {
99          TapeDeckStateMachineHandler handler = new TapeDeckStateMachineHandler();
100 
101         StateMachine sm = StateMachineFactory.getInstance(Transition.class).create(TapeDeckStateMachineHandler.S1, handler);
102 
103         TapeDeck player = new StateMachineProxyBuilder().create(TapeDeck.class, sm);
104         player.insert("Kings of convenience - Riot on an empty street");
105         player.start();
106         player.pause();
107         player.pause();
108         player.eject();
109         player.stop();
110         player.eject();
111 
112         LinkedList<String> messages = handler.messages;
113         assertEquals("Tape 'Kings of convenience - Riot on an empty street' inserted", messages.removeFirst());
114         assertEquals("Playing", messages.removeFirst());
115         assertEquals("Paused", messages.removeFirst());
116         assertEquals("Playing", messages.removeFirst());
117         assertEquals("Error: Cannot eject at this time", messages.removeFirst());
118         assertEquals("Stopped", messages.removeFirst());
119         assertEquals("Tape ejected", messages.removeFirst());
120         assertTrue(messages.isEmpty());
121     }
122     
123     public interface Reentrant {
124         void call1(Reentrant proxy);
125         void call2(Reentrant proxy);
126         void call3(Reentrant proxy);
127     }
128 
129     public static class ReentrantStateMachineHandler {
130         private boolean finished = false;
131 
132         public void call1(Reentrant proxy) {
133             proxy.call2(proxy);
134         }
135 
136         public void call2(Reentrant proxy) {
137             proxy.call3(proxy);
138         }
139 
140         public void call3(Reentrant proxy) {
141             finished = true;
142         }
143     }
144 
145     public interface TapeDeck {
146         void insert(String name);
147         void eject();
148         void start();
149         void pause();
150         void stop();
151     }
152     
153     public static class TapeDeckStateMachineHandler {
154         @org.apache.mina.statemachine.annotation.State public static final String PARENT = "parent";
155         @org.apache.mina.statemachine.annotation.State(PARENT) public static final String S1 = "s1";
156         @org.apache.mina.statemachine.annotation.State(PARENT) public static final String S2 = "s2";
157         @org.apache.mina.statemachine.annotation.State(PARENT) public static final String S3 = "s3";
158         @org.apache.mina.statemachine.annotation.State(PARENT) public static final String S4 = "s4";
159         @org.apache.mina.statemachine.annotation.State(PARENT) public static final String S5 = "s5";
160         
161         private LinkedList<String> messages = new LinkedList<String>();
162         
163         @Transition(on = "insert", in = "s1", next = "s2")
164         public void inserted(String name) {
165             messages.add("Tape '" + name + "' inserted");
166         }
167 
168         @Transition(on = "eject", in = "s4", next = "s1")
169         public void ejected() {
170             messages.add("Tape ejected");
171         }
172         
173         @Transitions({@Transition( on = "start", in = "s2", next = "s3" ),
174                    @Transition( on = "pause", in = "s5", next = "s3" )})
175         public void playing() {
176             messages.add("Playing");
177         }
178         
179         @Transition(on = "pause", in = "s3", next = "s5")
180         public void paused() {
181             messages.add("Paused");
182         }
183 
184         @Transition(on = "stop", in = "s3", next = "s4")
185         public void stopped() {
186             messages.add("Stopped");
187         }
188 
189         @Transition(on = "*", in = "parent")
190         public void error(Event event) {
191             messages.add("Error: Cannot " + event.getId() + " at this time");
192         }
193     }
194 }