diff --git a/pom.xml b/pom.xml index a1ec63b..2644ff4 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ me.bvn13.fsm fsm - 2.1.9 + 2.2.1 jar diff --git a/readme.md b/readme.md index 749fdfb..7939d74 100644 --- a/readme.md +++ b/readme.md @@ -50,6 +50,31 @@ Simple way to use it - to construct an inherited class specified with the type o .create(); ``` +or since 2.2.1 + +```java + SimpleFsm simpleFsm = Fsm + ., String>from(SimpleFsm::new) + .withStates() + .from("init") + .withBeforeHandler(fsm -> initBefore.set(true)) + .withAfterHandler(fsm -> initAfter.set(true)) + .withProcessor((fsm, event) -> initProcess.set(true)) + .withTransition() + .to("finish") + .checking((fsm, event) -> true) + .endTransition() + .end() + .finish("finish") + .withBeforeHandler(fsm -> finishBefore.set(true)) + .withAfterHandler(fsm -> finishAfter.set(true)) + .withProcessor((fsm, event) -> finishProcess.set(true)) + .end() + .create(); + } + +``` + ## Releasing Creating a new release involves the following steps: diff --git a/src/main/java/me/bvn13/fsm/ConditionBuilder.java b/src/main/java/me/bvn13/fsm/ConditionBuilder.java index ccdb607..230f087 100644 --- a/src/main/java/me/bvn13/fsm/ConditionBuilder.java +++ b/src/main/java/me/bvn13/fsm/ConditionBuilder.java @@ -3,12 +3,20 @@ package me.bvn13.fsm; public class ConditionBuilder { private final FsmBuilder fsmBuilder; + private final StateBuilder stateBuilder; private String from; private String to; private Condition condition; ConditionBuilder(FsmBuilder fsmBuilder) { this.fsmBuilder = fsmBuilder; + this.stateBuilder = null; + } + + ConditionBuilder(FsmBuilder fsmBuilder, StateBuilder stateBuilder, String from) { + this.fsmBuilder = fsmBuilder; + this.stateBuilder = stateBuilder; + this.from = from; } public ConditionBuilder from(String from) { @@ -31,4 +39,12 @@ public class ConditionBuilder { return fsmBuilder; } + public StateBuilder endTransition() { + if (stateBuilder == null) { + throw new IllegalStateException("Use '.end()' instead"); + } + end(); + return stateBuilder; + } + } diff --git a/src/main/java/me/bvn13/fsm/Fsm.java b/src/main/java/me/bvn13/fsm/Fsm.java index f724986..5f694e3 100644 --- a/src/main/java/me/bvn13/fsm/Fsm.java +++ b/src/main/java/me/bvn13/fsm/Fsm.java @@ -52,6 +52,8 @@ import static java.lang.String.format; * Simple way to use it - to construct an inherited class specified with the type of events to be processed * during transitions. * + * since 2.1.5 + * *
  *  {@code
  *  SimpleFsm simpleFsm = Fsm
@@ -76,6 +78,31 @@ import static java.lang.String.format;
  *  }
  * 
* + * or since 2.2.1 + * + *
+ *  {@code
+ *  SimpleFsm simpleFsm = Fsm
+ *    ., String>from(SimpleFsm::new)
+ *    .withStates()
+ *      .from("init")
+ *      .withBeforeHandler(fsm -> initBefore.set(true))
+ *      .withAfterHandler(fsm -> initAfter.set(true))
+ *      .withProcessor((fsm, event) -> initProcess.set(true))
+ *      .withTransition()
+ *        .to("finish")
+ *        .checking((fsm, event) -> true)
+ *      .endTransition()
+ *    .end()
+ *    .finish("finish")
+ *      .withBeforeHandler(fsm -> finishBefore.set(true))
+ *      .withAfterHandler(fsm -> finishAfter.set(true))
+ *      .withProcessor((fsm, event) -> finishProcess.set(true))
+ *    .end()
+ *    .create();
+ *  }
+ * 
+ * *

* Otherwise you are able to use Old syntax: * diff --git a/src/main/java/me/bvn13/fsm/StateBuilder.java b/src/main/java/me/bvn13/fsm/StateBuilder.java index 5af28a8..f6bb0e4 100644 --- a/src/main/java/me/bvn13/fsm/StateBuilder.java +++ b/src/main/java/me/bvn13/fsm/StateBuilder.java @@ -56,4 +56,8 @@ public class StateBuilder { return this; } + public ConditionBuilder withTransition() { + return new ConditionBuilder<>(fsmBuilder, this, name); + } + } diff --git a/src/test/java/me/bvn13/fsm/tests/FsmTest.java b/src/test/java/me/bvn13/fsm/tests/FsmTest.java index a02e733..fbee2b3 100644 --- a/src/test/java/me/bvn13/fsm/tests/FsmTest.java +++ b/src/test/java/me/bvn13/fsm/tests/FsmTest.java @@ -262,6 +262,78 @@ public class FsmTest { } + @Test + public void newSyntaxOfTransitions() { + + Counter initCounter = new Counter(); + Counter firstIntermediateCounter = new Counter(); + Counter secondIntermediateCounter = new Counter(); + Counter finishCounter = new Counter(); + + // @formatter:off + + SimpleFsm simpleFsm = Fsm + ., String>from(SimpleFsm::new) + .withStates() + .from("init") + .withBeforeHandler(fsm -> initCounter.before.incrementAndGet()) + .withProcessor((fsm, event) -> initCounter.process.incrementAndGet()) + .withAfterHandler(fsm -> initCounter.after.incrementAndGet()) + .withTransition() + .to("intermediate-1") + .checking((fsm, event) -> true) + .endTransition() + .end() + .state("intermediate-1") + .withBeforeHandler(fsm -> firstIntermediateCounter.before.incrementAndGet()) + .withProcessor((fsm, event) -> firstIntermediateCounter.process.incrementAndGet()) + .withAfterHandler(fsm -> firstIntermediateCounter.after.incrementAndGet()) + .withTransition() + .from("intermediate-1") + .to("intermediate-2") + .checking((fsm, event) -> true) + .endTransition() + .end() + .state("intermediate-2") + .withBeforeHandler(fsm -> secondIntermediateCounter.before.incrementAndGet()) + .withProcessor((fsm, event) -> secondIntermediateCounter.process.incrementAndGet()) + .withAfterHandler(fsm -> secondIntermediateCounter.after.incrementAndGet()) + .end() + .finish("finish") + .withBeforeHandler(fsm -> finishCounter.before.incrementAndGet()) + .withProcessor((fsm, event) -> finishCounter.process.incrementAndGet()) + .withAfterHandler(fsm -> finishCounter.after.incrementAndGet()) + .withTransition() + .from("intermediate-2") + .to("finish") + .checking((fsm, event) -> true) + .endTransition() + .end() + .create() + ; + + // @formatter:on + + simpleFsm.process(""); + simpleFsm.process(""); + simpleFsm.process(""); + + Assert.assertEquals("finish", simpleFsm.getCurrentState().getName()); + Assert.assertEquals(1, initCounter.before.get()); + Assert.assertEquals(1, initCounter.after.get()); + Assert.assertEquals(1, initCounter.process.get()); + Assert.assertEquals(1, firstIntermediateCounter.before.get()); + Assert.assertEquals(1, firstIntermediateCounter.after.get()); + Assert.assertEquals(1, firstIntermediateCounter.process.get()); + Assert.assertEquals(1, secondIntermediateCounter.before.get()); + Assert.assertEquals(1, secondIntermediateCounter.after.get()); + Assert.assertEquals(1, secondIntermediateCounter.process.get()); + Assert.assertEquals(1, finishCounter.before.get()); + Assert.assertEquals(0, finishCounter.after.get()); + Assert.assertEquals(0, finishCounter.process.get()); + + } + static class Counter { final AtomicInteger before = new AtomicInteger(0); final AtomicInteger after = new AtomicInteger(0);