Merge branch 'release/2.1.1'

This commit is contained in:
Vyacheslav Boyko 2022-07-07 23:22:15 +03:00
commit 81c5deb923
3 changed files with 61 additions and 36 deletions

View File

@ -7,7 +7,7 @@
<groupId>me.bvn13</groupId> <groupId>me.bvn13</groupId>
<artifactId>fsm</artifactId> <artifactId>fsm</artifactId>
<version>2.0</version> <version>2.1.1</version>
<packaging>jar</packaging> <packaging>jar</packaging>

View File

@ -3,7 +3,6 @@ package me.bvn13.fsm;
import me.bvn13.fsm.exceptions.AmbiguousTransitionException; import me.bvn13.fsm.exceptions.AmbiguousTransitionException;
import me.bvn13.fsm.exceptions.BrokenTransitionException; import me.bvn13.fsm.exceptions.BrokenTransitionException;
import me.bvn13.fsm.exceptions.ConditionAlreadyExistsException; import me.bvn13.fsm.exceptions.ConditionAlreadyExistsException;
import me.bvn13.fsm.exceptions.FsmException;
import me.bvn13.fsm.exceptions.NotInitializedException; import me.bvn13.fsm.exceptions.NotInitializedException;
import me.bvn13.fsm.exceptions.StateAlreadyExistsException; import me.bvn13.fsm.exceptions.StateAlreadyExistsException;
import me.bvn13.fsm.exceptions.TransitionMissedException; import me.bvn13.fsm.exceptions.TransitionMissedException;
@ -16,11 +15,11 @@ import java.util.function.Supplier;
/** /**
* <p> * <p>
* <b>Final State Machine</b><br/> * <b>Final State Machine</b>
* </p> * </p>
* <p> * <p>
* <ol>
* Each state machine must be prepared with: * Each state machine must be prepared with:
* <ol>
* <li>Initial state</li> * <li>Initial state</li>
* <li>Finish state - may be not several states</li> * <li>Finish state - may be not several states</li>
* <li>Intermediate states - optionally</li> * <li>Intermediate states - optionally</li>
@ -29,8 +28,8 @@ import java.util.function.Supplier;
* </p> * </p>
* *
* <p> * <p>
* <ol>
* Each {@link State} may be specified with handlers: * Each {@link State} may be specified with handlers:
* <ol>
* <li>Before handler - is called right before FSM changes INTO this state</li> * <li>Before handler - is called right before FSM changes INTO this state</li>
* <li>After handler - is called right before FSM changes FROM this state to another</li> * <li>After handler - is called right before FSM changes FROM this state to another</li>
* <li>Processor - the method to process events</li> * <li>Processor - the method to process events</li>
@ -39,7 +38,7 @@ import java.util.function.Supplier;
* *
* <p> * <p>
* Transition is the Rule providing FSM the possibility to change between states. * Transition is the Rule providing FSM the possibility to change between states.
* * <p>
* Each transition must be determined in terms of: * Each transition must be determined in terms of:
* <ol> * <ol>
* <li>From State - mandatory</li> * <li>From State - mandatory</li>
@ -49,9 +48,11 @@ import java.util.function.Supplier;
* </ol> * </ol>
* </p> * </p>
* *
* * <p>
* Simple way to use it - to construct an inherited class specified with the type of events to be processed * Simple way to use it - to construct an inherited class specified with the type of events to be processed
* during transitions. * during transitions.
* </p>
*
* <pre> * <pre>
* {@code * {@code
* SimpleFsm<String> simpleFsm = Fsm * SimpleFsm<String> simpleFsm = Fsm
@ -73,8 +74,40 @@ import java.util.function.Supplier;
* .checking((fsm, event) -> true) * .checking((fsm, event) -> true)
* .end() * .end()
* .create(); * .create();
* }
* </pre> * </pre>
* *
* <p>
* Otherwise you are able to use Old syntax:
* </p>
*
* <pre>
* {@code
* NamedFsm namedFsm = new NamedFsm().setName("TEST FSM");
* namedFsm.initState(new State<String>("init") {
* @Override
* public void process(String event) {
* initStatedProcessed.set(true);
* }
* });
*
* namedFsm.addTransition("init", new State<String>("first", true) {
* @Override
* public void process(String event) {
* firstStatedProcessed.set(true);
* }
* });
*
* namedFsm.addTransition("init", new State<String>("another", true) {
* @Override
* public void process(String event) {
* anotherStatedProcessed.set(true);
* }
* }, (fsm, event) -> false);
*
* namedFsm.init();
* }
* </pre> *
* {@link SimpleFsm} * {@link SimpleFsm}
*/ */
public class Fsm<T extends Fsm, E> { public class Fsm<T extends Fsm, E> {
@ -84,26 +117,25 @@ public class Fsm<T extends Fsm, E> {
private State<E> currentState; private State<E> currentState;
private State<E> previousState; private State<E> previousState;
private final Map<String, State<E>> states = new HashMap<>(); private final Map<String, State<E>> states = new HashMap<>();
private final Map<String, Map<String, Condition<T,E>>> transitions = new HashMap<>(); private final Map<String, Map<String, Condition<T, E>>> transitions = new HashMap<>();
/** /**
* Initiate a builder * Initiate a builder
* *
* @param supplier the original FSM inherited class constructor. You may specify '{@code () -> new SimpleFsm()}' in parameter * @param supplier the original FSM inherited class constructor. You may specify '{@code () -> new SimpleFsm()}' in parameter
* @return FsmBuilder
* @param <T> the original FSM inherited class type * @param <T> the original FSM inherited class type
* @param <E> the class type of Events to be processed * @param <E> the class type of Events to be processed
* @return FsmBuilder
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T extends Fsm,E> FsmBuilderInitializer<T,E> from(Supplier<T> supplier) { public static <T extends Fsm, E> FsmBuilderInitializer<T, E> from(Supplier<T> supplier) {
return new FsmBuilderInitializer<>(supplier); return new FsmBuilderInitializer<>(supplier);
} }
/** /**
* To initialize FSM into initial state * To initialize FSM into initial state
* @throws NotInitializedException
*/ */
public void init() throws NotInitializedException { public void init() {
currentState = initialState; currentState = initialState;
if (currentState == null) { if (currentState == null) {
throw new NotInitializedException(); throw new NotInitializedException();
@ -117,10 +149,9 @@ public class Fsm<T extends Fsm, E> {
* Main method to handle every event * Main method to handle every event
* *
* @param event event * @param event event
* @throws FsmException
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void process(E event) throws FsmException { public void process(E event) {
if (done) { if (done) {
return; return;
} }
@ -155,9 +186,8 @@ public class Fsm<T extends Fsm, E> {
* To specify initial state * To specify initial state
* *
* @param state {@link State} * @param state {@link State}
* @throws FsmException
*/ */
public void initState(State<E> state) throws FsmException { public void initState(State<E> state) {
state.setFSM(this); state.setFSM(this);
addState(state); addState(state);
initialState = state; initialState = state;
@ -167,9 +197,8 @@ public class Fsm<T extends Fsm, E> {
* To add another state * To add another state
* *
* @param state {@link State} * @param state {@link State}
* @throws FsmException
*/ */
public void addState(State<E> state) throws FsmException { public void addState(State<E> state) {
checkStateExist(state.getName()); checkStateExist(state.getName());
state.setFSM(this); state.setFSM(this);
this.states.put(state.getName(), state); this.states.put(state.getName(), state);
@ -180,9 +209,8 @@ public class Fsm<T extends Fsm, E> {
* *
* @param fromState {@link State} * @param fromState {@link State}
* @param toState {@link State} * @param toState {@link State}
* @throws FsmException
*/ */
public void addTransition(String fromState, String toState) throws FsmException { public void addTransition(String fromState, String toState) {
storeTransition(fromState, toState, null); storeTransition(fromState, toState, null);
} }
@ -192,9 +220,8 @@ public class Fsm<T extends Fsm, E> {
* @param fromState {@link State} * @param fromState {@link State}
* @param toState {@link State} * @param toState {@link State}
* @param condition {@link Condition} * @param condition {@link Condition}
* @throws FsmException
*/ */
public void addTransition(String fromState, String toState, Condition<T,E> condition) throws FsmException { public void addTransition(String fromState, String toState, Condition<T, E> condition) {
storeTransition(fromState, toState, condition); storeTransition(fromState, toState, condition);
} }
@ -203,9 +230,8 @@ public class Fsm<T extends Fsm, E> {
* *
* @param fromState {@link State} * @param fromState {@link State}
* @param toState {@link State} * @param toState {@link State}
* @throws FsmException
*/ */
public void addTransition(String fromState, State<E> toState) throws FsmException { public void addTransition(String fromState, State<E> toState) {
addState(toState); addState(toState);
addTransition(fromState, toState.getName()); addTransition(fromState, toState.getName());
} }
@ -216,9 +242,8 @@ public class Fsm<T extends Fsm, E> {
* @param fromState {@link State} * @param fromState {@link State}
* @param toState {@link State} * @param toState {@link State}
* @param condition {@link Condition} * @param condition {@link Condition}
* @throws FsmException
*/ */
public void addTransition(String fromState, State<E> toState, Condition<T,E> condition) throws FsmException { public void addTransition(String fromState, State<E> toState, Condition<T, E> condition) {
addState(toState); addState(toState);
addTransition(fromState, toState.getName(), condition); addTransition(fromState, toState.getName(), condition);
} }
@ -227,12 +252,12 @@ public class Fsm<T extends Fsm, E> {
if (!transitions.containsKey(currentState.getName())) { if (!transitions.containsKey(currentState.getName())) {
throw new TransitionMissedException(currentState.getName()); throw new TransitionMissedException(currentState.getName());
} }
Map<String, Condition<T,E>> conditions = transitions.get(currentState.getName()); Map<String, Condition<T, E>> conditions = transitions.get(currentState.getName());
List<String> nextStates = new ArrayList<>(); List<String> nextStates = new ArrayList<>();
for (String key : conditions.keySet()) { for (String key : conditions.keySet()) {
if (conditions.get(key) == null) { if (conditions.get(key) == null) {
nextStates.add(key); nextStates.add(key);
} else if(conditions.get(key).check((T) this, event)) { } else if (conditions.get(key).check((T) this, event)) {
nextStates.add(key); nextStates.add(key);
} }
} }
@ -258,7 +283,7 @@ public class Fsm<T extends Fsm, E> {
} }
} }
private void storeTransition(String fromState, String toState, Condition<T,E> condition) throws FsmException { private void storeTransition(String fromState, String toState, Condition<T, E> condition) {
if (!transitions.containsKey(fromState)) { if (!transitions.containsKey(fromState)) {
transitions.put(fromState, new HashMap<>()); transitions.put(fromState, new HashMap<>());
} }

View File

@ -1,7 +1,7 @@
package me.bvn13.fsm.exceptions; package me.bvn13.fsm.exceptions;
/** /**
* is thrown in case of adding a transition FROM->TO, but it is already defined * is thrown in case of adding a transition <code>FROM->TO</code>, but it is already defined
*/ */
public class ConditionAlreadyExistsException extends FsmException { public class ConditionAlreadyExistsException extends FsmException {
public ConditionAlreadyExistsException(String from, String to) { public ConditionAlreadyExistsException(String from, String to) {