First example

Javadoc for this example.

src_examples/net/sourceforge/anotherfsm/examples/first/package-info.java
/* * Copyright 2013 Michal Turek, AnotherFSM * * http://anotherfsm.sourceforge.net/ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */   /** * Introduction to the main features of AnotherFSM library. * * The code searches "AnotherFSM" string in the user input and exits the * application after it is entered. Of course this implementation is an overkill * solution for such simple task, remember it's only a demonstration. * * <h3>Classes</h3> * * <ul> * <li>{@link net.sourceforge.anotherfsm.examples.first.SearchFsm} * Defines structure of the state machine.</li> * <li>{@link net.sourceforge.anotherfsm.examples.first.SearchFsmProcessor} * Defines listeners for the states and transitions.</li> * <li>{@link net.sourceforge.anotherfsm.examples.first.FirstExample} * Defines main() method, passes data to the state machine.</li> * </ul> * * @author Michal Turek */ package net.sourceforge.anotherfsm.examples.first;
src_examples/net/sourceforge/anotherfsm/examples/first/SearchFsm.java
/* * Copyright 2013 Michal Turek, AnotherFSM * * http://anotherfsm.sourceforge.net/ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */   package net.sourceforge.anotherfsm.examples.first;   import net.sourceforge.anotherfsm.CharacterEvent; import net.sourceforge.anotherfsm.DeterministicStateMachine; import net.sourceforge.anotherfsm.FsmException; import net.sourceforge.anotherfsm.OtherEvent; import net.sourceforge.anotherfsm.State; import net.sourceforge.anotherfsm.Transition;   /** * State machine to search hard coded "AnotherFSM" string. This class will be * generated from state machine schema after the editor and/or generator is * implemented. * * Note the state machine is not fully correct. Every state should also contain * transition on 'A' character to {@link #stateA} but this was ignored for * simplicity. * * @author Michal Turek */ class SearchFsm extends DeterministicStateMachine { // The states public final State stateStart; public final State stateA; public final State stateN; public final State stateO; public final State stateT; public final State stateH; public final State stateE; public final State stateR; public final State stateF; public final State stateS; public final State stateM;   // The transitions to search "AnotherFSM" string public final Transition trStartToA; public final Transition trAtoN; public final Transition trNtoO; public final Transition trOtoT; public final Transition trTtoH; public final Transition trHtoE; public final Transition trEtoR; public final Transition trRtoF; public final Transition trFtoS; public final Transition trStoM;   // The transitions to return searching to the beginning on bad input public final Transition trStartOther; public final Transition trAOther; public final Transition trNOther; public final Transition trOOther; public final Transition trTOther; public final Transition trHOther; public final Transition trEOther; public final Transition trROther; public final Transition trFOther; public final Transition trSOther; public final Transition trMOther;   /** * Create the object, build the state machine. * * @param name * the name of the state machine * @throws FsmException * if building of state machine fails */ public SearchFsm(String name) throws FsmException { super(name);   // Create the states stateStart = new State("Start state"); stateA = new State("State A"); stateN = new State("State N"); stateO = new State("State O"); stateT = new State("State T"); stateH = new State("State H"); stateE = new State("State E"); stateR = new State("State R"); stateF = new State("State F"); stateS = new State("State S"); stateM = new State("State M", State.Type.FINAL);   // Create the transitions for searching trStartToA = new Transition(stateStart, CharacterEvent.instance('A'), stateA); trAtoN = new Transition(stateA, CharacterEvent.instance('n'), stateN); trNtoO = new Transition(stateN, CharacterEvent.instance('o'), stateO); trOtoT = new Transition(stateO, CharacterEvent.instance('t'), stateT); trTtoH = new Transition(stateT, CharacterEvent.instance('h'), stateH); trHtoE = new Transition(stateH, CharacterEvent.instance('e'), stateE); trEtoR = new Transition(stateE, CharacterEvent.instance('r'), stateR); trRtoF = new Transition(stateR, CharacterEvent.instance('F'), stateF); trFtoS = new Transition(stateF, CharacterEvent.instance('S'), stateS); trStoM = new Transition(stateS, CharacterEvent.instance('M'), stateM);   // Create the transitions for bad input trStartOther = new Transition(stateStart, OtherEvent.instance, stateStart); trAOther = new Transition(stateA, OtherEvent.instance, stateStart); trNOther = new Transition(stateN, OtherEvent.instance, stateStart); trOOther = new Transition(stateO, OtherEvent.instance, stateStart); trTOther = new Transition(stateT, OtherEvent.instance, stateStart); trHOther = new Transition(stateH, OtherEvent.instance, stateStart); trEOther = new Transition(stateE, OtherEvent.instance, stateStart); trROther = new Transition(stateR, OtherEvent.instance, stateStart); trFOther = new Transition(stateF, OtherEvent.instance, stateStart); trSOther = new Transition(stateS, OtherEvent.instance, stateStart); trMOther = new Transition(stateM, OtherEvent.instance, stateStart);   // Register states addState(stateStart); addState(stateA); addState(stateN); addState(stateO); addState(stateT); addState(stateH); addState(stateE); addState(stateR); addState(stateF); addState(stateS); addState(stateM);   // Register transitions for searching addTransition(trStartToA); addTransition(trAtoN); addTransition(trNtoO); addTransition(trOtoT); addTransition(trTtoH); addTransition(trHtoE); addTransition(trEtoR); addTransition(trRtoF); addTransition(trFtoS); addTransition(trStoM);   // Register transitions for bad input addTransition(trStartOther); addTransition(trAOther); addTransition(trNOther); addTransition(trOOther); addTransition(trTOther); addTransition(trHOther); addTransition(trEOther); addTransition(trROther); addTransition(trFOther); addTransition(trSOther); addTransition(trMOther);   // Define the start state setStartState(stateStart); } }  
src_examples/net/sourceforge/anotherfsm/examples/first/SearchFsmProcessor.java
/* * Copyright 2013 Michal Turek, AnotherFSM * * http://anotherfsm.sourceforge.net/ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */   package net.sourceforge.anotherfsm.examples.first;   import net.sourceforge.anotherfsm.CharacterEvent; import net.sourceforge.anotherfsm.EqualsPreprocessor; import net.sourceforge.anotherfsm.Event; import net.sourceforge.anotherfsm.FsmException; import net.sourceforge.anotherfsm.OtherEvent; import net.sourceforge.anotherfsm.Preprocessor; import net.sourceforge.anotherfsm.State; import net.sourceforge.anotherfsm.StateAdapter; import net.sourceforge.anotherfsm.TransitionListener;   /** * Listeners of the state machine. This class is more a demonstration of the * features than something useful. * * @author Michal Turek */ public class SearchFsmProcessor extends SearchFsm { /** * Create the object. * * @param name * the name of the state machine * @throws FsmException * if building of state machine fails */ public SearchFsmProcessor(String name) throws FsmException { super(name);   // Create a new preprocessor that is based on equals() method of events EqualsPreprocessor preprocessor = new EqualsPreprocessor(name);   // Don't pass newline characters to the state machine preprocessor.addProcessor(CharacterEvent.instance('\n'), new Preprocessor.Processor<CharacterEvent>() { @Override public Event process(CharacterEvent event) { // Null stops the event processing in preprocessor return null; } });   // Register preprocessor to the state machine addPreprocessor(preprocessor);   // Do something on enter of state A stateA.addListener(new StateAdapter() { @Override public void onStateEnter(State previous, Event event, State current) { logger.info("Character 'A' entered, good start."); } });   // Do something on transition from state R to state F trRtoF.addListener(new TransitionListener() { @Override public void onTransition(State source, Event event, State destination) { logger.info("Great, nearly done, please continue."); } });   // Do something on any transition addListener(new TransitionListener() { @Override public void onTransition(State source, Event event, State destination) { // State machine tries to process OtherEvent event if no // transition matches if (event instanceof OtherEvent) { logger.info("Oh bad character, let's start again..."); } } });   // Do something on enter of any state addListener(new StateAdapter() { @Override public void onStateEnter(State previous, Event event, State current) { // The last state of the string is a final state if (current.isFinalState()) { logger.info("Whole string successfully entered."); } } }); } }  
src_examples/net/sourceforge/anotherfsm/examples/first/FirstExample.java
/* * Copyright 2013 Michal Turek, AnotherFSM * * http://anotherfsm.sourceforge.net/ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */   package net.sourceforge.anotherfsm.examples.first;   import java.io.IOException;   import net.sourceforge.anotherfsm.AnotherFsm; import net.sourceforge.anotherfsm.CharacterEvent; import net.sourceforge.anotherfsm.FsmException; import net.sourceforge.anotherfsm.StateMachine; import net.sourceforge.anotherfsm.logger.FsmLogger; import net.sourceforge.anotherfsm.logger.StdStreamLoggerFactory;   /** * Search "AnotherFSM" string in the input from user and exit the application * after it is entered. * * @author Michal Turek */ public class FirstExample { static { // Register factory of loggers before any logger is created AnotherFsm.setLoggerFactory(new StdStreamLoggerFactory()); }   /** The logger object for this class. */ private final static FsmLogger logger = AnotherFsm .getLogger(FirstExample.class);   /** * The application start function. * * @param args * the input arguments, unused */ public static void main(String[] args) { // Create instance of the state machine try (StateMachine machine = new SearchFsmProcessor( FirstExample.class.getSimpleName())) { // Building done in the constructor, prepare for events processing machine.start();   logger.info("Type 'AnotherFSM' string to exit.");   while (true) { // Read a character from user and pass it to the state machine char c = (char) System.in.read(); machine.process(CharacterEvent.instance(c));   // Exit after a final state is entered if (machine.isInFinalState()) { logger.debug("'AnotherFSM' string found in input, exiting"); break; } } } catch (FsmException | IOException e) { // Process any exception that may occur logger.fatal("Unexpected exception occurred", e); }   logger.debug("End of main()"); } }  

Sample outputs

2013-01-18 18:35:56,137 [main]  INFO SearchFsmProcessor.FirstExample - Transition started:  @INITIAL@ -> StartEvent -> Start state
2013-01-18 18:35:56,144 [main]  INFO SearchFsmProcessor.FirstExample - Transition finished: @INITIAL@ -> StartEvent -> Start state
2013-01-18 18:35:56,144 [main]  INFO FirstExample - Type 'AnotherFSM' string to exit.
AnotherFSM
2013-01-18 18:36:06,265 [main]  INFO SearchFsmProcessor.FirstExample - Transition started:  Start state -> CharacterEvent(A) -> State A
2013-01-18 18:36:06,265 [main]  INFO SearchFsmProcessor.FirstExample - Character 'A' entered, good start.
2013-01-18 18:36:06,265 [main]  INFO SearchFsmProcessor.FirstExample - Transition finished: Start state -> CharacterEvent(A) -> State A
2013-01-18 18:36:06,266 [main]  INFO SearchFsmProcessor.FirstExample - Transition started:  State A -> CharacterEvent(n) -> State N
2013-01-18 18:36:06,266 [main]  INFO SearchFsmProcessor.FirstExample - Transition finished: State A -> CharacterEvent(n) -> State N
2013-01-18 18:36:06,266 [main]  INFO SearchFsmProcessor.FirstExample - Transition started:  State N -> CharacterEvent(o) -> State O
2013-01-18 18:36:06,266 [main]  INFO SearchFsmProcessor.FirstExample - Transition finished: State N -> CharacterEvent(o) -> State O
2013-01-18 18:36:06,267 [main]  INFO SearchFsmProcessor.FirstExample - Transition started:  State O -> CharacterEvent(t) -> State T
2013-01-18 18:36:06,267 [main]  INFO SearchFsmProcessor.FirstExample - Transition finished: State O -> CharacterEvent(t) -> State T
2013-01-18 18:36:06,267 [main]  INFO SearchFsmProcessor.FirstExample - Transition started:  State T -> CharacterEvent(h) -> State H
2013-01-18 18:36:06,267 [main]  INFO SearchFsmProcessor.FirstExample - Transition finished: State T -> CharacterEvent(h) -> State H
2013-01-18 18:36:06,268 [main]  INFO SearchFsmProcessor.FirstExample - Transition started:  State H -> CharacterEvent(e) -> State E
2013-01-18 18:36:06,268 [main]  INFO SearchFsmProcessor.FirstExample - Transition finished: State H -> CharacterEvent(e) -> State E
2013-01-18 18:36:06,268 [main]  INFO SearchFsmProcessor.FirstExample - Transition started:  State E -> CharacterEvent(r) -> State R
2013-01-18 18:36:06,268 [main]  INFO SearchFsmProcessor.FirstExample - Transition finished: State E -> CharacterEvent(r) -> State R
2013-01-18 18:36:06,269 [main]  INFO SearchFsmProcessor.FirstExample - Transition started:  State R -> CharacterEvent(F) -> State F
2013-01-18 18:36:06,269 [main]  INFO SearchFsmProcessor.FirstExample - Great, nearly done, please continue.
2013-01-18 18:36:06,269 [main]  INFO SearchFsmProcessor.FirstExample - Transition finished: State R -> CharacterEvent(F) -> State F
2013-01-18 18:36:06,269 [main]  INFO SearchFsmProcessor.FirstExample - Transition started:  State F -> CharacterEvent(S) -> State S
2013-01-18 18:36:06,270 [main]  INFO SearchFsmProcessor.FirstExample - Transition finished: State F -> CharacterEvent(S) -> State S
2013-01-18 18:36:06,270 [main]  INFO SearchFsmProcessor.FirstExample - Transition started:  State S -> CharacterEvent(M) -> State M
2013-01-18 18:36:06,270 [main]  INFO SearchFsmProcessor.FirstExample - Whole string successfully entered.
2013-01-18 18:36:06,270 [main]  INFO SearchFsmProcessor.FirstExample - Transition finished: State S -> CharacterEvent(M) -> State M
2013-01-18 18:36:06,271 [main] DEBUG FirstExample - 'AnotherFSM' string found in input, exiting
2013-01-18 18:36:06,271 [main] DEBUG FirstExample - End of main()
2013-01-18 18:36:28,590 [main]  INFO SearchFsmProcessor.FirstExample - Transition started:  @INITIAL@ -> StartEvent -> Start state
2013-01-18 18:36:28,600 [main]  INFO SearchFsmProcessor.FirstExample - Transition finished: @INITIAL@ -> StartEvent -> Start state
2013-01-18 18:36:28,600 [main]  INFO FirstExample - Type 'AnotherFSM' string to exit.
Ano
2013-01-18 18:36:33,742 [main]  INFO SearchFsmProcessor.FirstExample - Transition started:  Start state -> CharacterEvent(A) -> State A
2013-01-18 18:36:33,743 [main]  INFO SearchFsmProcessor.FirstExample - Character 'A' entered, good start.
2013-01-18 18:36:33,743 [main]  INFO SearchFsmProcessor.FirstExample - Transition finished: Start state -> CharacterEvent(A) -> State A
2013-01-18 18:36:33,743 [main]  INFO SearchFsmProcessor.FirstExample - Transition started:  State A -> CharacterEvent(n) -> State N
2013-01-18 18:36:33,744 [main]  INFO SearchFsmProcessor.FirstExample - Transition finished: State A -> CharacterEvent(n) -> State N
2013-01-18 18:36:33,744 [main]  INFO SearchFsmProcessor.FirstExample - Transition started:  State N -> CharacterEvent(o) -> State O
2013-01-18 18:36:33,744 [main]  INFO SearchFsmProcessor.FirstExample - Transition finished: State N -> CharacterEvent(o) -> State O
2013-01-18 18:36:33,744 [main]  INFO EqualsPreprocessor.FirstExample - Event preprocessed: CharacterEvent(
) -> null
X
2013-01-18 18:36:44,280 [main]  INFO SearchFsmProcessor.FirstExample - Transition started:  State O -> CharacterEvent(X)/OtherEvent(CharacterEvent(X)) -> Start state
2013-01-18 18:36:44,281 [main]  INFO SearchFsmProcessor.FirstExample - Oh bad character, let's start again...
2013-01-18 18:36:44,281 [main]  INFO SearchFsmProcessor.FirstExample - Transition finished: State O -> CharacterEvent(X)/OtherEvent(CharacterEvent(X)) -> Start state
2013-01-18 18:36:44,281 [main]  INFO EqualsPreprocessor.FirstExample - Event preprocessed: CharacterEvent(
) -> null
Y
2013-01-18 18:36:53,689 [main]  INFO SearchFsmProcessor.FirstExample - Transition started:  Start state -> CharacterEvent(Y)/OtherEvent(CharacterEvent(Y)) -> Start state
2013-01-18 18:36:53,690 [main]  INFO SearchFsmProcessor.FirstExample - Oh bad character, let's start again...
2013-01-18 18:36:53,690 [main]  INFO SearchFsmProcessor.FirstExample - Transition finished: Start state -> CharacterEvent(Y)/OtherEvent(CharacterEvent(Y)) -> Start state
2013-01-18 18:36:53,690 [main]  INFO EqualsPreprocessor.FirstExample - Event preprocessed: CharacterEvent(
) -> null
...