/*
* Copyright 2015-2017 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.statemachine.support;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.junit.Test;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.statemachine.ExtendedState;
import org.springframework.statemachine.StateContext;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.access.StateMachineAccessor;
import org.springframework.statemachine.action.Action;
import org.springframework.statemachine.action.ActionListener;
import org.springframework.statemachine.listener.StateMachineListener;
import org.springframework.statemachine.security.SecurityRule;
import org.springframework.statemachine.state.EnumState;
import org.springframework.statemachine.state.State;
import org.springframework.statemachine.transition.Transition;
import org.springframework.statemachine.transition.TransitionKind;
import org.springframework.statemachine.trigger.Trigger;
public class StateContextExpressionMethodsTests {
@Test
public void testGuardBooleanExpressions() {
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
StateContextExpressionMethods methods = new StateContextExpressionMethods(evaluationContext);
StateContext<SpelStates, SpelEvents> stateContext = mockStateContext(null);
assertThat(methods.getValue(parser.parseExpression("true"), stateContext, Boolean.class), is(true));
assertThat(methods.getValue(parser.parseExpression("event.toString().equals('E1')"), stateContext, Boolean.class), is(true));
assertThat(methods.getValue(parser.parseExpression("event==T(org.springframework.statemachine.support.StateContextExpressionMethodsTests.SpelEvents).E1"), stateContext, Boolean.class), is(true));
assertThat(methods.getValue(parser.parseExpression("getExtendedState().getVariables().get('boolean1')"), stateContext, Boolean.class), is(true));
assertThat(methods.getValue(parser.parseExpression("extendedState.variables.get('boolean1')"), stateContext, Boolean.class), is(true));
assertThat(methods.getValue(parser.parseExpression("extendedState.variables.get('boolean1')&&!extendedState.variables.get('boolean2')"), stateContext, Boolean.class), is(true));
assertThat(methods.getValue(parser.parseExpression("extendedState.variables.get('boolean3')==NULL"), stateContext, Boolean.class), is(true));
assertThat(methods.getValue(parser.parseExpression("transition.source.id.toString().equals('S1')"), stateContext, Boolean.class), is(true));
}
@Test
public void testSendEvent() {
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
StateContextExpressionMethods methods = new StateContextExpressionMethods(evaluationContext);
MockStatemachine stateMachine = new MockStatemachine();
StateContext<SpelStates, SpelEvents> stateContext = mockStateContext(stateMachine);
assertThat(methods.getValue(parser.parseExpression("stateMachine.sendEvent(T(org.springframework.statemachine.support.StateContextExpressionMethodsTests.SpelEvents).E1)"), stateContext, Boolean.class), is(true));
assertThat(stateMachine.events.size(), is(1));
}
enum SpelStates {
SI,S1,S2,S3,S4,SF,SH
}
public enum SpelEvents {
E1,E2,E3,E4,EF
}
private StateContext<SpelStates, SpelEvents> mockStateContext(StateMachine<SpelStates, SpelEvents> stateMachine) {
Map<String, Object> headers = new HashMap<String, Object>();
headers.put("foo", "bar");
MessageHeaders messageHeaders = new MessageHeaders(headers);
ExtendedState extendedState = new DefaultExtendedState();
extendedState.getVariables().put("key1", "val1");
extendedState.getVariables().put("boolean1", true);
extendedState.getVariables().put("boolean2", false);
StateContext<SpelStates, SpelEvents> stateContext = new DefaultStateContext<SpelStates, SpelEvents>(
null, MessageBuilder.withPayload(SpelEvents.E1).build(), messageHeaders, extendedState, new MockTransition(), stateMachine, null, null, null);
return stateContext;
}
private static class MockTransition implements Transition<SpelStates, SpelEvents> {
@Override
public boolean transit(StateContext<SpelStates, SpelEvents> context) {
return false;
}
@Override
public void executeTransitionActions(StateContext<SpelStates, SpelEvents> context) {
}
@Override
public State<SpelStates, SpelEvents> getSource() {
return new EnumState<SpelStates, SpelEvents>(SpelStates.S1);
}
@Override
public State<SpelStates, SpelEvents> getTarget() {
return new EnumState<SpelStates, SpelEvents>(SpelStates.S2);
}
@Override
public Collection<Action<SpelStates, SpelEvents>> getActions() {
return null;
}
@Override
public Trigger<SpelStates, SpelEvents> getTrigger() {
return null;
}
@Override
public TransitionKind getKind() {
return null;
}
@Override
public SecurityRule getSecurityRule() {
return null;
}
@Override
public void addActionListener(ActionListener<SpelStates, SpelEvents> listener) {
}
@Override
public void removeActionListener(ActionListener<SpelStates, SpelEvents> listener) {
}
}
private static class MockStatemachine implements StateMachine<SpelStates, SpelEvents> {
ArrayList<Message<SpelEvents>> events = new ArrayList<Message<SpelEvents>>();
@Override
public StateMachineAccessor<SpelStates, SpelEvents> getStateMachineAccessor() {
return null;
}
@Override
public void start() {
}
@Override
public void stop() {
}
@Override
public boolean sendEvent(Message<SpelEvents> event) {
events.add(event);
return true;
}
@Override
public boolean sendEvent(SpelEvents event) {
return sendEvent(MessageBuilder.createMessage(event, new MessageHeaders(new HashMap<String, Object>())));
}
@Override
public State<SpelStates, SpelEvents> getState() {
return null;
}
@Override
public Collection<State<SpelStates, SpelEvents>> getStates() {
return null;
}
@Override
public Collection<Transition<SpelStates, SpelEvents>> getTransitions() {
return null;
}
@Override
public boolean isComplete() {
return false;
}
@Override
public void setStateMachineError(Exception exception) {
}
@Override
public boolean hasStateMachineError() {
return false;
}
@Override
public void addStateListener(StateMachineListener<SpelStates, SpelEvents> listener) {
}
@Override
public void removeStateListener(StateMachineListener<SpelStates, SpelEvents> listener) {
}
@Override
public State<SpelStates, SpelEvents> getInitialState() {
return null;
}
@Override
public ExtendedState getExtendedState() {
return null;
}
@Override
public UUID getUuid() {
return null;
}
@Override
public String getId() {
return null;
}
}
}