com.alibaba.cola.statemachine.impl.StateMachineImpl Maven / Gradle / Ivy
package com.alibaba.cola.statemachine.impl;
import com.alibaba.cola.statemachine.State;
import com.alibaba.cola.statemachine.StateMachine;
import com.alibaba.cola.statemachine.Transition;
import com.alibaba.cola.statemachine.Visitor;
import java.util.List;
import java.util.Map;
/**
* For performance consideration,
* The state machine is made "stateless" on purpose.
* Once it's built, it can be shared by multi-thread
*
* One side effect is since the state machine is stateless, we can not get current state from State Machine.
*
* @author Frank Zhang
* @date 2020-02-07 5:40 PM
*/
public class StateMachineImpl implements StateMachine {
private String machineId;
private final Map> stateMap;
private boolean ready;
public StateMachineImpl(Map> stateMap) {
this.stateMap = stateMap;
}
@Override
public S fireEvent(S sourceStateId, E event, C ctx) {
isReady();
Transition transition = routeTransition(sourceStateId, event, ctx);
if (transition == null) {
Debugger.debug("There is no Transition for " + event);
return sourceStateId;
}
return transition.transit(ctx).getId();
}
private Transition routeTransition(S sourceStateId, E event, C ctx) {
State sourceState = getState(sourceStateId);
List> transitions = sourceState.getEventTransitions(event);
if (transitions == null || transitions.size() == 0) {
return null;
}
Transition transit = null;
for (Transition transition : transitions) {
if (transition.getCondition() == null) {
transit = transition;
} else if (transition.getCondition().isSatisfied(ctx)) {
transit = transition;
break;
}
}
return transit;
}
private State getState(S currentStateId) {
State state = StateHelper.getState(stateMap, currentStateId);
if (state == null) {
showStateMachine();
throw new StateMachineException(currentStateId + " is not found, please check state machine");
}
return state;
}
private void isReady() {
if (!ready) {
throw new StateMachineException("State machine is not built yet, can not work");
}
}
@Override
public String accept(Visitor visitor) {
StringBuilder sb = new StringBuilder();
sb.append(visitor.visitOnEntry(this));
for (State state : stateMap.values()) {
sb.append(state.accept(visitor));
}
sb.append(visitor.visitOnExit(this));
return sb.toString();
}
@Override
public void showStateMachine() {
SysOutVisitor sysOutVisitor = new SysOutVisitor();
accept(sysOutVisitor);
}
@Override
public String generatePlantUML() {
PlantUMLVisitor plantUMLVisitor = new PlantUMLVisitor();
return accept(plantUMLVisitor);
}
@Override
public String getMachineId() {
return machineId;
}
public void setMachineId(String machineId) {
this.machineId = machineId;
}
public void setReady(boolean ready) {
this.ready = ready;
}
}