io.github.yangziwen.quickstate.impl.StateMachineImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of quick-state Show documentation
Show all versions of quick-state Show documentation
A lightweight state machine
package io.github.yangziwen.quickstate.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import io.github.yangziwen.quickstate.State;
import io.github.yangziwen.quickstate.StateMachine;
import io.github.yangziwen.quickstate.Transition;
import io.github.yangziwen.quickstate.Visitor;
import lombok.Getter;
import lombok.Setter;
public class StateMachineImpl implements StateMachine {
@Getter
private final String id;
private final Map> stateMap;
@Getter
@Setter
private boolean ready;
public StateMachineImpl(String id, Map> stateMap) {
this.id = id;
this.stateMap = stateMap;
}
@Override
public List> getAllStates() {
return new ArrayList<>(stateMap.values());
}
@Override
public List> getTransitions(S sourceId) {
State source = ensureState(sourceId);
return source.getAllTransitions();
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
@Override
@SuppressWarnings("unchecked")
public S fire(S sourceId, E event, C context) {
if (!ready) {
throw new StateMachineException("State machine[" + id + "] is not built yet, can not work");
}
if (context instanceof ContextImpl) {
ContextImpl.class.cast(context).setStateMachine(this);
}
State source = ensureState(sourceId);
State target = doTransition(source, event, context);
return target != null ? target.getId() : null;
}
@Override
public boolean canApply(S sourceId, E event) {
State source = ensureState(sourceId);
List> transitions = source.getTransitions(event);
return CollectionUtils.isNotEmpty(transitions);
}
private State doTransition(State source, E event, C context) {
List> transitions = source.getTransitions(event);
if (CollectionUtils.isEmpty(transitions)) {
return null;
}
for (Transition transition : transitions) {
if (transition.test(context)) {
return transition.transit(context);
}
}
return null;
}
private State ensureState(S stateId) {
State state = stateMap.get(stateId);
if(state == null) {
state = new StateImpl<>(stateId);
stateMap.put(stateId, state);
}
return state;
}
@Override
public String toString() {
return "state machine[" + getId() + "] with states [" + StringUtils.join(stateMap.keySet().toArray(), ", ") + "]";
}
}