![JAR search and dependency download from the Maven repository](/logo.png)
com.github.oxo42.stateless4j.StateRepresentation Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of stateless4j Show documentation
Show all versions of stateless4j Show documentation
A fluent interface for state machines
package com.github.oxo42.stateless4j;
import com.github.oxo42.stateless4j.delegates.Action1;
import com.github.oxo42.stateless4j.delegates.Action2;
import com.github.oxo42.stateless4j.transitions.Transition;
import com.github.oxo42.stateless4j.triggers.TriggerBehaviour;
import java.util.*;
public class StateRepresentation {
private final TState state;
private final Map>> triggerBehaviours = new HashMap<>();
private final List, Object[]>> entryActions = new ArrayList<>();
private final List>> exitActions = new ArrayList<>();
private final List> substates = new ArrayList<>();
private StateRepresentation superstate; // null
public StateRepresentation(TState state) {
this.state = state;
}
protected Map>> getTriggerBehaviours() {
return triggerBehaviours;
}
public Boolean canHandle(TTrigger trigger) {
return tryFindHandler(trigger) != null;
}
public TriggerBehaviour tryFindHandler(TTrigger trigger) {
TriggerBehaviour result = tryFindLocalHandler(trigger);
if (result == null && superstate != null) {
result = superstate.tryFindHandler(trigger);
}
return result;
}
TriggerBehaviour tryFindLocalHandler(TTrigger trigger/*, out TriggerBehaviour handler*/) {
List> possible = triggerBehaviours.get(trigger);
if (possible == null) {
return null;
}
List> actual = new ArrayList<>();
for (TriggerBehaviour triggerBehaviour : possible) {
if (triggerBehaviour.isGuardConditionMet()) {
actual.add(triggerBehaviour);
}
}
if (actual.size() > 1) {
throw new IllegalStateException("Multiple permitted exit transitions are configured from state '" + trigger + "' for trigger '" + state + "'. Guard clauses must be mutually exclusive.");
}
return actual.get(0);
}
public void addEntryAction(final TTrigger trigger, final Action2, Object[]> action) {
assert action != null : "action is null";
entryActions.add(new Action2, Object[]>() {
@Override
public void doIt(Transition t, Object[] args) {
if (t.getTrigger().equals(trigger)) {
action.doIt(t, args);
}
}
});
}
public void addEntryAction(Action2, Object[]> action) {
assert action != null : "action is null";
entryActions.add(action);
}
public void insertEntryAction(Action2, Object[]> action) {
assert action != null : "action is null";
entryActions.add(0, action);
}
public void addExitAction(Action1> action) {
assert action != null : "action is null";
exitActions.add(action);
}
public void enter(Transition transition, Object... entryArgs) {
assert transition != null : "transition is null";
if (transition.isReentry()) {
executeEntryActions(transition, entryArgs);
} else if (!includes(transition.getSource())) {
if (superstate != null) {
superstate.enter(transition, entryArgs);
}
executeEntryActions(transition, entryArgs);
}
}
public void exit(Transition transition) {
assert transition != null : "transition is null";
if (transition.isReentry()) {
executeExitActions(transition);
} else if (!includes(transition.getDestination())) {
executeExitActions(transition);
if (superstate != null) {
superstate.exit(transition);
}
}
}
void executeEntryActions(Transition transition, Object[] entryArgs) {
assert transition != null : "transition is null";
assert entryArgs != null : "entryArgs is null";
for (Action2, Object[]> action : entryActions) {
action.doIt(transition, entryArgs);
}
}
void executeExitActions(Transition transition) {
assert transition != null : "transition is null";
for (Action1> action : exitActions) {
action.doIt(transition);
}
}
public void addTriggerBehaviour(TriggerBehaviour triggerBehaviour) {
List> allowed;
if (!triggerBehaviours.containsKey(triggerBehaviour.getTrigger())) {
allowed = new ArrayList<>();
triggerBehaviours.put(triggerBehaviour.getTrigger(), allowed);
}
allowed = triggerBehaviours.get(triggerBehaviour.getTrigger());
allowed.add(triggerBehaviour);
}
public StateRepresentation getSuperstate() {
return superstate;
}
public void setSuperstate(StateRepresentation value) {
superstate = value;
}
public TState getUnderlyingState() {
return state;
}
public void addSubstate(StateRepresentation substate) {
assert substate != null : "substate is null";
substates.add(substate);
}
public boolean includes(TState stateToCheck) {
for (StateRepresentation s : substates) {
if (s.includes(stateToCheck)) {
return true;
}
}
return this.state.equals(stateToCheck);
}
public boolean isIncludedIn(TState stateToCheck) {
return this.state.equals(stateToCheck) || (superstate != null && superstate.isIncludedIn(stateToCheck));
}
@SuppressWarnings("unchecked")
public List getPermittedTriggers() {
Set result = new HashSet<>();
for (TTrigger t : triggerBehaviours.keySet()) {
for (TriggerBehaviour v : triggerBehaviours.get(t)) {
if (v.isGuardConditionMet()) {
result.add(t);
break;
}
}
}
if (getSuperstate() != null) {
result.addAll(getSuperstate().getPermittedTriggers());
}
return new ArrayList<>(result);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy