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
...