Code Examples
A repository of 155 code examples for BeepBeep
SimpleMooreMachine.java
1 /*
2  BeepBeep, an event stream processor
3  Copyright (C) 2008-2017 Sylvain HallĂ©
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published
7  by the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 package finitestatemachines;
19 
20 import ca.uqac.lif.cep.Connector;
21 import ca.uqac.lif.cep.Pullable;
22 import ca.uqac.lif.cep.fsm.FunctionTransition;
23 import ca.uqac.lif.cep.fsm.MooreMachine;
24 import ca.uqac.lif.cep.functions.StreamVariable;
25 import ca.uqac.lif.cep.functions.Constant;
26 import ca.uqac.lif.cep.functions.FunctionTree;
27 import ca.uqac.lif.cep.tmf.QueueSource;
28 import ca.uqac.lif.cep.util.Equals;
29 
30 /**
31  * Check the proper ordering of next/hasNext strings. In this example, we
32  * suppose we get a stream of method calls on an <tt>Iterator</tt> object.
33  * The proper use of an iterator stipulates that one should never call method
34  * <code>next()</code> before first calling method <code>hasNext()</code>.
35  * The correct ordering of these calls can be expressed by a finite-state
36  * machine with three states.
37  * <p>
38  * On the input stream "hasNext", "next", "hasNext", "hasNext", "next", "next",
39  * the expected output of this program is:
40  * <pre>
41  * unsafe
42  * safe
43  * unsafe
44  * unsafe
45  * safe
46  * error
47  * error
48  * </pre>
49  * <p>
50  * The basic Moore machine is very generic. The conditions on its transitions
51  * can be arbitrary functions on incoming events; as a result, defining a
52  * simple state machine can be a little verbose. For a more "compact" way of
53  * defining the state machine in this example, see {@link SimpleMooreMachineCompact}.
54  *
55  * @see SimpleMooreMachineCompact#main(String[])
56  * @author Sylvain HallĂ©
57  *
58  */
59 public class SimpleMooreMachine
60 {
61  public static void main(String[] args)
62  {
63  ///
64  /* Create an empty Moore machine. This machine receives one stream of
65  * events as its input, and produces one stream of events as its
66  * output. */
67  MooreMachine machine = new MooreMachine(1, 1);
68 
69  /* Define symbolic constants for the three states of the
70  * Moore machine. It is recommended that the actual numbers for
71  * each state form a contiguous interval of integers starting
72  * at 0. */
73  final int UNSAFE = 0, SAFE = 1, ERROR = 2;
74 
75  /* Let us now define the transitions for this machine. This is just
76  * a tedious enumeration of all the arrows that are present in a
77  * graphical representation of the FSM. First, in state 0, if the
78  * incoming event is equal to "hasNext", go to state 1.
79  *
80  * By default, the first state number that is ever given to the
81  * MooreMachine object is taken as the initial state of that machine.
82  * So here, UNSAFE will be the initial state. There can be only one
83  * initial state. */
84  machine.addTransition(UNSAFE, new FunctionTransition(
85  new FunctionTree(Equals.instance,
86  StreamVariable.X, new Constant("hasNext")), SAFE));
87  /* In state 0, if the incoming event is equal to "next", go to state 2 */
88  machine.addTransition(UNSAFE, new FunctionTransition(
89  new FunctionTree(Equals.instance,
90  StreamVariable.X, new Constant("next")), ERROR));
91  /* In state 1, if the incoming event is equal to "next", go to state 0 */
92  machine.addTransition(SAFE, new FunctionTransition(
93  new FunctionTree(Equals.instance,
94  StreamVariable.X, new Constant("next")), UNSAFE));
95  /* In state 1, if the incoming event is equal to "hasNext", stay in state 1 */
96  machine.addTransition(SAFE, new FunctionTransition(
97  new FunctionTree(Equals.instance,
98  StreamVariable.X, new Constant("hasNext")), SAFE));
99  /* State 2 is a sink, you stay there forever. A possible way to say so
100  * is to define the condition on its only transition as the constant true;
101  * it will fire whatever the incoming event. */
102  machine.addTransition(ERROR, new FunctionTransition(
103  new Constant(true), ERROR));
104  ///
105 
106  /* Since a Moore machine outputs a symbol when jumping into a
107  * new state, we must associate symbols to each of the three states.
108  * These symbols can be any object; here we use Boolean values. */
109  //*
110  machine.addSymbol(UNSAFE, new Constant(true));
111  machine.addSymbol(SAFE, new Constant(true));
112  machine.addSymbol(ERROR, new Constant(false));
113  //*
114 
115  /* Done! We can now try our Moore machine on a sequence of events .*/
116  //!
117  QueueSource source = new QueueSource();
118  source.setEvents("hasNext", "next", "hasNext",
119  "hasNext", "next", "next");
120  Connector.connect(source, machine);
121 
122  /* Let's pull a few events to see what comes out... */
123  Pullable p = machine.getPullableOutput();
124  for (int i = 0; i < 7; i++)
125  {
126  Boolean b = (Boolean) p.pull();
127  System.out.println(b);
128  }
129  //!
130  }
131 
132 }
Check the proper ordering of next/hasNext strings.