/* * Copyright 2015-2016 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.state; import java.util.ArrayList; import java.util.Collection; import org.springframework.messaging.Message; import org.springframework.statemachine.StateContext; import org.springframework.statemachine.action.Action; import org.springframework.statemachine.region.Region; import org.springframework.statemachine.support.StateMachineUtils; /** * A {@link State} implementation where states are wrapped in a regions.. * * @author Janne Valkealahti * * @param <S> the type of state * @param <E> the type of event */ public class RegionState<S, E> extends AbstractState<S, E> { /** * Instantiates a new region state. * * @param id the state identifier * @param regions the regions */ public RegionState(S id, Collection<Region<S, E>> regions) { super(id, null, null, null, null, regions); } /** * Instantiates a new region state. * * @param id the state identifier * @param regions the regions * @param deferred the deferred */ public RegionState(S id, Collection<Region<S, E>> regions, Collection<E> deferred) { super(id, deferred, null, null, null, regions); } /** * Instantiates a new region state. * * @param id the state identifier * @param regions the regions * @param pseudoState the pseudo state */ public RegionState(S id, Collection<Region<S, E>> regions, PseudoState<S, E> pseudoState) { super(id, null, null, null, pseudoState, regions); } /** * Instantiates a new region state. * * @param id the state identifier * @param regions the regions * @param deferred the deferred * @param entryActions the entry actions * @param exitActions the exit actions * @param pseudoState the pseudo state */ public RegionState(S id, Collection<Region<S, E>> regions, Collection<E> deferred, Collection<? extends Action<S, E>> entryActions, Collection<? extends Action<S, E>> exitActions, PseudoState<S, E> pseudoState) { super(id, deferred, entryActions, exitActions, pseudoState, regions); } /** * Instantiates a new region state. * * @param id the state identifier * @param regions the regions * @param deferred the deferred * @param entryActions the entry actions * @param exitActions the exit actions */ public RegionState(S id, Collection<Region<S, E>> regions, Collection<E> deferred, Collection<? extends Action<S, E>> entryActions, Collection<? extends Action<S, E>> exitActions) { super(id, deferred, entryActions, exitActions, null, regions); } @Override public boolean sendEvent(Message<E> event) { boolean accept = false; if (getRegions() != null) { for (Region<S, E> r : getRegions()) { accept |= r.sendEvent(event); } } return accept; } @Override public boolean shouldDefer(Message<E> event) { boolean defer = true; if (getRegions() != null) { for (Region<S, E> r : getRegions()) { State<S, E> state = r.getState(); if (state != null) { if (state.getDeferredEvents().contains(event.getPayload())) { defer = defer & true; } else { defer = false; } } } } return defer; } @Override public void exit(StateContext<S, E> context) { super.exit(context); for (Region<S, E> region : getRegions()) { if (region.getState() != null) { region.getState().exit(context); } region.stop(); } for (Action<S, E> action : getExitActions()) { executeAction(action, context); } } @Override public void entry(StateContext<S, E> context) { super.entry(context); for (Action<S, E> action : getEntryActions()) { executeAction(action, context); } if (getPseudoState() != null && getPseudoState().getKind() == PseudoStateKind.INITIAL) { for (Region<S, E> region : getRegions()) { boolean start = true; if (StateMachineUtils.containsAtleastOne(region.getStates(), context.getTargets())) { start = false; } if (start) { region.start(); } } } else { for (Region<S, E> region : getRegions()) { if (region.getState() != null) { region.getState().entry(context); } } } } @Override public Collection<S> getIds() { ArrayList<S> ids = new ArrayList<S>(); if (getId() != null) { ids.add(getId()); } for (Region<S, E> r : getRegions()) { State<S, E> s = r.getState(); if (s != null) { ids.addAll(s.getIds()); } } return ids; } @Override public Collection<State<S, E>> getStates() { ArrayList<State<S, E>> states = new ArrayList<State<S, E>>(); states.add(this); for (Region<S, E> r : getRegions()) { for (State<S, E> s : r.getStates()) { states.addAll(s.getStates()); } } return states; } @Override public String toString() { return "RegionState [getIds()=" + getIds() + ", getClass()=" + getClass() + ", hashCode()=" + hashCode() + ", toString()=" + super.toString() + "]"; } }