package org.squirrelframework.foundation.fsm;
import org.squirrelframework.foundation.component.Observable;
import org.squirrelframework.foundation.event.SquirrelEvent;
import org.squirrelframework.foundation.exception.TransitionException;
import org.squirrelframework.foundation.fsm.ActionExecutionService.BeforeExecActionListener;
import org.squirrelframework.foundation.util.ReflectUtils;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;
/**
* Interface for finite state machine.
*
* @author Henry.He
*
* @param <T> type of State Machine
* @param <S> type of State
* @param <E> type of Event
* @param <C> type of Context
*/
public interface StateMachine<T extends StateMachine<T, S, E, C>, S, E, C> extends Visitable, Observable {
/**
* Fires the specified event
* @param event the event
* @param context external context
*/
void fire(E event, C context);
/**
* Fires event with context immediately, if current state machine is busy, the next processing event
* is this event.
* @param event the event
* @param context external context
*/
void fireImmediate(E event, C context);
/**
* Test transition result under circumstance
* @param event test event
* @param context text context
* @return test transition result
*/
S test(E event, C context);
/**
* Fire event
* @param event
*/
void fire(E event);
/**
* Fire event immediately
* @param event
*/
void fireImmediate(E event);
/**
* Test event
* @param event
*/
S test(E event);
/**
* @param event test event
* @return true is passed in event is acceptable otherwise return false
*/
boolean canAccept(E event);
/**
* Start state machine under external context
* @param context external context
*/
void start(C context);
/**
* Start state machine without context
*/
void start();
/**
* Terminate state machine under external context
* @param context external context
*/
void terminate(C context);
/**
* Terminate state machine without context
*/
void terminate();
/**
* @return current status of state machine
*/
StateMachineStatus getStatus();
/**
* @return type-safe state machine instance
*/
T getThis();
/**
* @return current state id of state machine
*/
S getCurrentState();
/**
* @return last active state id of state machine
*/
S getLastState();
/**
* @return id of state machine initial state
*/
S getInitialState();
/**
* @param parentStateId id of parent state
* @return last active child state of the parent state
*/
S getLastActiveChildStateOf(S parentStateId);
/**
* @param parentStateId
* @return sub state of parallel state
*/
List<S> getSubStatesOn(S parentStateId);
/**
* @return current raw state of state machine
*/
ImmutableState<T, S, E, C> getCurrentRawState();
/**
* @return last active raw state of state machine
*/
ImmutableState<T, S, E, C> getLastRawState();
/**
* @return initial raw state of state machine
*/
ImmutableState<T, S, E, C> getInitialRawState();
ImmutableState<T, S, E, C> getRawStateFrom(S stateId);
Collection<S> getAllStates();
Collection<ImmutableState<T, S, E, C>> getAllRawStates();
/**
* Dump current state machine data. This operation can only be done when state machine status is
* {@link StateMachineStatus#IDLE}, otherwise null will be returned.
*
* @return dumped state machine data reader
*/
StateMachineData.Reader<T, S, E, C> dumpSavedData();
/**
* Load saved data for current state machine. The operation can only be done when state machine
* status is {@link StateMachineStatus#INITIALIZED} or {@link StateMachineStatus#TERMINATED}.
*
* @param savedData provided saved data
* @return true if load saved data success otherwise false
*/
boolean loadSavedData(StateMachineData.Reader<T, S, E, C> savedData);
/**
* @return whether state machine is context sensitive
*/
@Deprecated
boolean isContextSensitive();
Class<C> typeOfContext();
Class<E> typeOfEvent();
Class<S> typeOfState();
TransitionException getLastException();
String getIdentifier();
String getDescription();
String exportXMLDefinition(boolean beautifyXml);
void addDeclarativeListener(Object listener);
void removeDeclarativeListener(Object listener);
boolean isRemoteMonitorEnabled();
boolean isStarted();
boolean isTerminated();
boolean isError();
interface StateMachineListener<T extends StateMachine<T, S, E, C>, S, E, C> {
public static final String METHOD_NAME = "stateMachineEvent";
// leverage bridge method to call the method of actual listener
public static final Method METHOD = ReflectUtils.getMethod(
StateMachineListener.class, METHOD_NAME, new Class<?>[]{StateMachineEvent.class});
void stateMachineEvent(StateMachineEvent<T, S, E, C> event);
}
interface StateMachineEvent<T extends StateMachine<T, S, E, C>, S, E, C> extends SquirrelEvent {
T getStateMachine();
}
void addStateMachineListener(StateMachineListener<T, S, E, C> listener);
void removeStateMachineListener(StateMachineListener<T, S, E, C> listener);
interface StartListener<T extends StateMachine<T, S, E, C>, S, E, C> {
public static final String METHOD_NAME = "started";
public static final Method METHOD = ReflectUtils.getMethod(
StartListener.class, METHOD_NAME, new Class<?>[]{StartEvent.class});
void started(StartEvent<T, S, E, C> event);
}
interface StartEvent <T extends StateMachine<T, S, E, C>, S, E, C> extends StateMachineEvent<T, S, E, C> {}
void addStartListener(StartListener<T, S, E, C> listener);
void removeStartListener(StartListener<T, S, E, C> listener);
interface TerminateListener<T extends StateMachine<T, S, E, C>, S, E, C> {
public static final String METHOD_NAME = "terminated";
public static final Method METHOD = ReflectUtils.getMethod(
TerminateListener.class, METHOD_NAME, new Class<?>[]{TerminateEvent.class});
void terminated(TerminateEvent<T, S, E, C> event);
}
interface TerminateEvent <T extends StateMachine<T, S, E, C>, S, E, C> extends StateMachineEvent<T, S, E, C> {}
void addTerminateListener(TerminateListener<T, S, E, C> listener);
void removeTerminateListener(TerminateListener<T, S, E, C> listener);
interface StateMachineExceptionListener<T extends StateMachine<T, S, E, C>, S, E, C> {
public static final String METHOD_NAME = "stateMachineException";
public static final Method METHOD = ReflectUtils.getMethod(
StateMachineExceptionListener.class, METHOD_NAME, new Class<?>[]{StateMachineExceptionEvent.class});
void stateMachineException(StateMachineExceptionEvent<T, S, E, C> event);
}
interface StateMachineExceptionEvent<T extends StateMachine<T, S, E, C>, S, E, C> extends StateMachineEvent<T, S, E, C> {
Exception getException();
}
void addStateMachineExceptionListener(StateMachineExceptionListener<T, S, E, C> listener);
void removeStateMachineExceptionListener(StateMachineExceptionListener<T, S, E, C> listener);
interface TransitionEvent<T extends StateMachine<T, S, E, C>, S, E, C> extends StateMachineEvent<T, S, E, C> {
S getSourceState();
E getCause();
C getContext();
}
interface TransitionBeginListener<T extends StateMachine<T, S, E, C>, S, E, C> {
public static final String METHOD_NAME = "transitionBegin";
public static final Method METHOD = ReflectUtils.getMethod(
TransitionBeginListener.class, METHOD_NAME, new Class<?>[]{TransitionBeginEvent.class});
void transitionBegin(TransitionBeginEvent<T, S, E, C> event);
}
interface TransitionBeginEvent<T extends StateMachine<T, S, E, C>, S, E, C> extends TransitionEvent<T, S, E, C> {}
void addTransitionBeginListener(TransitionBeginListener<T, S, E, C> listener);
void removeTransitionBeginListener(TransitionBeginListener<T, S, E, C> listener);
interface TransitionCompleteListener<T extends StateMachine<T, S, E, C>, S, E, C> {
public static final String METHOD_NAME = "transitionComplete";
public static final Method METHOD = ReflectUtils.getMethod(
TransitionCompleteListener.class, METHOD_NAME, new Class<?>[]{TransitionCompleteEvent.class});
void transitionComplete(TransitionCompleteEvent<T, S, E, C> event);
}
interface TransitionCompleteEvent<T extends StateMachine<T, S, E, C>, S, E, C> extends TransitionEvent<T, S, E, C> {
S getTargetState();
}
void addTransitionCompleteListener(TransitionCompleteListener<T, S, E, C> listener);
void removeTransitionCompleteListener(TransitionCompleteListener<T, S, E, C> listener);
interface TransitionExceptionListener<T extends StateMachine<T, S, E, C>, S, E, C> {
public static final String METHOD_NAME = "transitionException";
public static final Method METHOD = ReflectUtils.getMethod(
TransitionExceptionListener.class, METHOD_NAME, new Class<?>[]{TransitionExceptionEvent.class});
void transitionException(TransitionExceptionEvent<T, S, E, C> event);
}
interface TransitionExceptionEvent<T extends StateMachine<T, S, E, C>, S, E, C> extends TransitionEvent<T, S, E, C> {
S getTargetState();
TransitionException getException();
}
void addTransitionExceptionListener(TransitionExceptionListener<T, S, E, C> listener);
void removeTransitionExceptionListener(TransitionExceptionListener<T, S, E, C> listener);
interface TransitionDeclinedListener<T extends StateMachine<T, S, E, C>, S, E, C> {
public static final String METHOD_NAME = "transitionDeclined";
public static final Method METHOD = ReflectUtils.getMethod(
TransitionDeclinedListener.class, METHOD_NAME, new Class<?>[]{TransitionDeclinedEvent.class});
void transitionDeclined(TransitionDeclinedEvent<T, S, E, C> event);
}
interface TransitionDeclinedEvent<T extends StateMachine<T, S, E, C>, S, E, C> extends TransitionEvent<T, S, E, C> {}
void addTransitionDeclinedListener(TransitionDeclinedListener<T, S, E, C> listener);
void removeTransitionDeclinedListener(TransitionDeclinedListener<T, S, E, C> listener);
@Deprecated
void removeTransitionDecleindListener(TransitionDeclinedListener<T, S, E, C> listener);
interface TransitionEndListener<T extends StateMachine<T, S, E, C>, S, E, C> {
public static final String METHOD_NAME = "transitionEnd";
public static final Method METHOD = ReflectUtils.getMethod(
TransitionEndListener.class, METHOD_NAME, new Class<?>[]{TransitionEndEvent.class});
void transitionEnd(TransitionEndEvent<T, S, E, C> event);
}
interface TransitionEndEvent<T extends StateMachine<T, S, E, C>, S, E, C> extends TransitionEvent<T, S, E, C> {
S getTargetState();
}
void addTransitionEndListener(TransitionEndListener<T, S, E, C> listener);
void removeTransitionEndListener(TransitionEndListener<T, S, E, C> listener);
void addExecActionListener(BeforeExecActionListener<T, S, E, C> listener);
void removeExecActionListener(BeforeExecActionListener<T, S, E, C> listener);
}