package org.expeditee.core; import java.util.ArrayList; import java.util.List; public class FSM { private int _currentState; private List _transitions; private List _nextTrueStates; private List _nextFalseStates; private List _finalStates; private boolean _inconsistent; public FSM() { _transitions = new ArrayList(); _nextTrueStates = new ArrayList(); _nextFalseStates = new ArrayList(); _finalStates = new ArrayList(); configureState(0, null, 0, 0, false); reset(); } /** * Resets the DFSM to its initial state. */ public void reset() { _currentState = 0; _inconsistent = false; } /** * Gets the current state of the DFSM. */ public int currentState() { return _currentState; } /** * Whether the DFSM is in a consistent state. May be false if a state has been incorrectly * configured causing a transition into unconfigured territory. */ public boolean isConsistent() { return !_inconsistent; } /** * Edits the configuration of a given state. * * @param state The state to configure. * @param transition The object to use for comparison to determine the next state. * @param nextTrueState The next state to go to if the input is equal to the transition object. * @param nextFalseState The next state to go to if the input is not equal to the transition object. * @param isFinalState Whether this state is a final state. */ public void configureState(int state, Object transition, int nextTrueState, int nextFalseState, boolean isFinalState) { if (state < 0 || nextTrueState < 0 || nextFalseState < 0) return; while (state > _transitions.size()) { _transitions.add(null); _nextTrueStates.add(null); _nextFalseStates.add(null); _finalStates.add(null); } _transitions.set(state, transition); _nextTrueStates.set(state, nextTrueState); _nextFalseStates.set(state, nextFalseState); _finalStates.set(state, isFinalState); } /** * Moves the DFSM to a new state based on comparing the input object to the transition * object for the current state. * * @param input The input object to compare to. */ public void input(Object input) { // Can't do anything if we are inconsistent if (_inconsistent) return; // Get the transition object for the current state Object transition = _transitions.get(_currentState); // Work out whether the input matches the transition object boolean result; if (transition == null) { result = input == null; } else { result = transition.equals(input); } // Work out which state to go to next Integer nextState; if (result) { nextState = _nextTrueStates.get(_currentState); } else { nextState = _nextFalseStates.get(_currentState); } // If there is no next state, we are inconsistent if (nextState == null) { _inconsistent = true; return; } // Go to the next state _currentState = nextState; } /** * Whether or not this DFSM is currently in a final state. */ public boolean isFinalState() { Boolean finalState = _finalStates.get(_currentState); return !_inconsistent && finalState != null && finalState.booleanValue(); } }