diff --git a/spring-statemachine-uml/src/main/java/org/springframework/statemachine/uml/support/UmlUtils.java b/spring-statemachine-uml/src/main/java/org/springframework/statemachine/uml/support/UmlUtils.java index 40ecf11c..276f31cc 100644 --- a/spring-statemachine-uml/src/main/java/org/springframework/statemachine/uml/support/UmlUtils.java +++ b/spring-statemachine-uml/src/main/java/org/springframework/statemachine/uml/support/UmlUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2018 the original author or authors. + * Copyright 2016-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,9 +37,14 @@ import org.eclipse.uml2.uml.Transition; import org.eclipse.uml2.uml.Trigger; import org.eclipse.uml2.uml.UMLPackage; import org.eclipse.uml2.uml.resource.UMLResource; +import org.springframework.expression.spel.SpelCompilerMode; +import org.springframework.expression.spel.SpelParserConfiguration; +import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.statemachine.action.Action; +import org.springframework.statemachine.action.SpelExpressionAction; import org.springframework.statemachine.config.model.StateMachineComponentResolver; import org.springframework.statemachine.transition.TransitionKind; +import org.springframework.util.StringUtils; /** * Utilities for uml model processing. @@ -138,9 +143,18 @@ public abstract class UmlUtils { Action action = null; if (transition.getEffect() instanceof OpaqueBehavior) { String beanId = UmlUtils.resolveBodyByLanguage(UmlModelParser.LANGUAGE_BEAN, (OpaqueBehavior)transition.getEffect()); - Action bean = resolver.resolveAction(beanId); - if (bean != null) { - action = bean; + if (StringUtils.hasText(beanId)) { + Action bean = resolver.resolveAction(beanId); + if (bean != null) { + action = bean; + } + } else { + String expression = UmlUtils.resolveBodyByLanguage(UmlModelParser.LANGUAGE_SPEL, (OpaqueBehavior)transition.getEffect()); + if (StringUtils.hasText(expression)) { + SpelExpressionParser parser = new SpelExpressionParser( + new SpelParserConfiguration(SpelCompilerMode.MIXED, null)); + action = new SpelExpressionAction(parser.parseExpression(expression)); + } } } return action; 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 d6d91073..cde38b17 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 @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -1122,6 +1122,20 @@ public class UmlStateMachineModelFactoryTests extends AbstractUmlTests { assertThat(choiceStateData.getParent(), is("S1")); } + @Test + @SuppressWarnings("unchecked") + public void testTransitionEffectSpel() { + context.register(Config27.class); + context.refresh(); + StateMachine stateMachine = context.getBean(StateMachine.class); + + stateMachine.start(); + assertThat(stateMachine.getState().getIds(), containsInAnyOrder("S1")); + stateMachine.sendEvent(MessageBuilder.withPayload("E1").build()); + assertThat(stateMachine.getState().getIds(), containsInAnyOrder("S2")); + assertThat(stateMachine.getExtendedState().get("key", String.class), is("value")); + } + @Configuration @EnableStateMachine public static class Config2 extends StateMachineConfigurerAdapter { @@ -1759,6 +1773,24 @@ public class UmlStateMachineModelFactoryTests extends AbstractUmlTests { } + @Configuration + @EnableStateMachine + public static class Config27 extends StateMachineConfigurerAdapter { + + @Override + public void configure(StateMachineModelConfigurer model) throws Exception { + model + .withModel() + .factory(modelFactory()); + } + + @Bean + public StateMachineModelFactory modelFactory() { + Resource model = new ClassPathResource("org/springframework/statemachine/uml/transition-effect-spel.uml"); + return new UmlStateMachineModelFactory(model); + } + } + 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/transition-effect-spel.di b/spring-statemachine-uml/src/test/resources/org/springframework/statemachine/uml/transition-effect-spel.di new file mode 100644 index 00000000..8c549eec --- /dev/null +++ b/spring-statemachine-uml/src/test/resources/org/springframework/statemachine/uml/transition-effect-spel.di @@ -0,0 +1,2 @@ + + diff --git a/spring-statemachine-uml/src/test/resources/org/springframework/statemachine/uml/transition-effect-spel.notation b/spring-statemachine-uml/src/test/resources/org/springframework/statemachine/uml/transition-effect-spel.notation new file mode 100644 index 00000000..3d056f3e --- /dev/null +++ b/spring-statemachine-uml/src/test/resources/org/springframework/statemachine/uml/transition-effect-spel.notation @@ -0,0 +1,93 @@ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-statemachine-uml/src/test/resources/org/springframework/statemachine/uml/transition-effect-spel.uml b/spring-statemachine-uml/src/test/resources/org/springframework/statemachine/uml/transition-effect-spel.uml new file mode 100644 index 00000000..401542a9 --- /dev/null +++ b/spring-statemachine-uml/src/test/resources/org/springframework/statemachine/uml/transition-effect-spel.uml @@ -0,0 +1,23 @@ + + + + + + + + + + + spel + extendedState.variables.put('key','value') + + + + + + + + + + +