From debc50cb563e7a2f7f0fa9fb8dd047372db2cacc Mon Sep 17 00:00:00 2001 From: Janne Valkealahti Date: Sat, 23 Apr 2016 09:46:37 +0100 Subject: [PATCH] Add support for timers in uml - Can now use timers based on TimeEvent, TimeExpression and LiteralInteger. - Fixes #207 --- .../config/model/TransitionData.java | 16 ++ .../uml/support/UmlModelParser.java | 23 +- .../uml/UmlStateMachineModelFactoryTests.java | 55 +++++ .../statemachine/uml/simple-timers.di | 2 + .../statemachine/uml/simple-timers.notation | 200 ++++++++++++++++++ .../statemachine/uml/simple-timers.uml | 50 +++++ 6 files changed, 345 insertions(+), 1 deletion(-) create mode 100644 spring-statemachine-uml/src/test/resources/org/springframework/statemachine/uml/simple-timers.di create mode 100644 spring-statemachine-uml/src/test/resources/org/springframework/statemachine/uml/simple-timers.notation create mode 100644 spring-statemachine-uml/src/test/resources/org/springframework/statemachine/uml/simple-timers.uml diff --git a/spring-statemachine-core/src/main/java/org/springframework/statemachine/config/model/TransitionData.java b/spring-statemachine-core/src/main/java/org/springframework/statemachine/config/model/TransitionData.java index 3b8aa888..e6646fc7 100644 --- a/spring-statemachine-core/src/main/java/org/springframework/statemachine/config/model/TransitionData.java +++ b/spring-statemachine-core/src/main/java/org/springframework/statemachine/config/model/TransitionData.java @@ -66,6 +66,22 @@ public class TransitionData { this(source, target, null, event, null, null, actions, guard, kind, null); } + /** + * Instantiates a new transition data. + * + * @param source the source + * @param target the target + * @param period the period + * @param count the count + * @param actions the actions + * @param guard the guard + * @param kind the kind + */ + public TransitionData(S source, S target, Long period, Integer count, Collection> actions, + Guard guard, TransitionKind kind) { + this(source, target, null, null, period, count, actions, guard, kind, null); + } + /** * Instantiates a new transition data. * diff --git a/spring-statemachine-uml/src/main/java/org/springframework/statemachine/uml/support/UmlModelParser.java b/spring-statemachine-uml/src/main/java/org/springframework/statemachine/uml/support/UmlModelParser.java index f2e76d16..ce9d3f36 100644 --- a/spring-statemachine-uml/src/main/java/org/springframework/statemachine/uml/support/UmlModelParser.java +++ b/spring-statemachine-uml/src/main/java/org/springframework/statemachine/uml/support/UmlModelParser.java @@ -38,6 +38,7 @@ import org.eclipse.uml2.uml.Signal; import org.eclipse.uml2.uml.SignalEvent; import org.eclipse.uml2.uml.State; import org.eclipse.uml2.uml.StateMachine; +import org.eclipse.uml2.uml.TimeEvent; import org.eclipse.uml2.uml.Transition; import org.eclipse.uml2.uml.Trigger; import org.eclipse.uml2.uml.UMLPackage; @@ -279,7 +280,7 @@ public class UmlModelParser { } // go through all triggers and create transition - // from signals + // from signals, or transitions from timers for (Trigger trigger : transition.getTriggers()) { Event event = trigger.getEvent(); if (event instanceof SignalEvent) { @@ -289,6 +290,18 @@ public class UmlModelParser { transition.getTarget().getName(), signal.getName(), resolveTransitionActions(transition), null, UmlUtils.mapUmlTransitionType(transition))); } + } else if (event instanceof TimeEvent) { + TimeEvent timeEvent = (TimeEvent)event; + Long period = getTimePeriod(timeEvent); + if (period != null) { + Integer count = null; + if (timeEvent.isRelative()) { + count = 1; + } + transitionDatas.add(new TransitionData(transition.getSource().getName(), + transition.getTarget().getName(), period, count, resolveTransitionActions(transition), null, + UmlUtils.mapUmlTransitionType(transition))); + } } } @@ -300,6 +313,14 @@ public class UmlModelParser { } } + private Long getTimePeriod(TimeEvent event) { + try { + return Long.valueOf(event.getWhen().getExpr().integerValue()); + } catch (Exception e) { + return null; + } + } + private Collection> resolveTransitionActions(Transition transition) { ArrayList> actions = new ArrayList>(); if (transition.getEffect() instanceof OpaqueBehavior) { diff --git a/spring-statemachine-uml/src/test/java/org/springframework/statemachine/uml/UmlStateMachineModelFactoryTests.java b/spring-statemachine-uml/src/test/java/org/springframework/statemachine/uml/UmlStateMachineModelFactoryTests.java index b5771b46..ab87ed0b 100644 --- a/spring-statemachine-uml/src/test/java/org/springframework/statemachine/uml/UmlStateMachineModelFactoryTests.java +++ b/spring-statemachine-uml/src/test/java/org/springframework/statemachine/uml/UmlStateMachineModelFactoryTests.java @@ -474,6 +474,34 @@ public class UmlStateMachineModelFactoryTests extends AbstractUmlTests { assertThat(stateMachine.getState().getIds(), containsInAnyOrder("S2", "S22")); } + @Test + @SuppressWarnings("unchecked") + public void testSimpleTimers1() throws Exception { + context.register(Config13.class); + context.refresh(); + StateMachine stateMachine = context.getBean(StateMachine.class); + LatchAction s3Entry = context.getBean("s3Entry", LatchAction.class); + stateMachine.start(); + assertThat(stateMachine.getState().getIds(), containsInAnyOrder("S1")); + stateMachine.sendEvent("E1"); + assertThat(s3Entry.latch.await(2, TimeUnit.SECONDS), is(true)); + assertThat(stateMachine.getState().getIds(), containsInAnyOrder("S3")); + } + + @Test + @SuppressWarnings("unchecked") + public void testSimpleTimers2() throws Exception { + context.register(Config13.class); + context.refresh(); + StateMachine stateMachine = context.getBean(StateMachine.class); + LatchAction s5Entry = context.getBean("s5Entry", LatchAction.class); + stateMachine.start(); + assertThat(stateMachine.getState().getIds(), containsInAnyOrder("S1")); + stateMachine.sendEvent("E2"); + assertThat(s5Entry.latch.await(2, TimeUnit.SECONDS), is(true)); + assertThat(stateMachine.getState().getIds(), containsInAnyOrder("S5")); + } + @Configuration @EnableStateMachine public static class Config2 extends StateMachineConfigurerAdapter { @@ -710,6 +738,33 @@ public class UmlStateMachineModelFactoryTests extends AbstractUmlTests { } } + @Configuration + @EnableStateMachine + public static class Config13 extends StateMachineConfigurerAdapter { + + @Override + public void configure(StateMachineModelConfigurer model) throws Exception { + model + .withModel() + .factory(modelFactory()); + } + + @Bean + public StateMachineModelFactory modelFactory() { + return new UmlStateMachineModelFactory("classpath:org/springframework/statemachine/uml/simple-timers.uml"); + } + + @Bean + public LatchAction s3Entry() { + return new LatchAction(); + } + + @Bean + public LatchAction s5Entry() { + return new LatchAction(); + } + } + public static class LatchAction implements Action { CountDownLatch latch = new CountDownLatch(1); @Override diff --git a/spring-statemachine-uml/src/test/resources/org/springframework/statemachine/uml/simple-timers.di b/spring-statemachine-uml/src/test/resources/org/springframework/statemachine/uml/simple-timers.di new file mode 100644 index 00000000..bf9abab3 --- /dev/null +++ b/spring-statemachine-uml/src/test/resources/org/springframework/statemachine/uml/simple-timers.di @@ -0,0 +1,2 @@ + + diff --git a/spring-statemachine-uml/src/test/resources/org/springframework/statemachine/uml/simple-timers.notation b/spring-statemachine-uml/src/test/resources/org/springframework/statemachine/uml/simple-timers.notation new file mode 100644 index 00000000..89312adb --- /dev/null +++ b/spring-statemachine-uml/src/test/resources/org/springframework/statemachine/uml/simple-timers.notation @@ -0,0 +1,200 @@ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-statemachine-uml/src/test/resources/org/springframework/statemachine/uml/simple-timers.uml b/spring-statemachine-uml/src/test/resources/org/springframework/statemachine/uml/simple-timers.uml new file mode 100644 index 00000000..3138f2a3 --- /dev/null +++ b/spring-statemachine-uml/src/test/resources/org/springframework/statemachine/uml/simple-timers.uml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + bean + s3Entry + + + + + + bean + s5Entry + + + + + + + + + + + + + + + + + + +