Reputation: 616
I am trying to find a way to render UI buttons (actions) depending on the object state. Is there a way to ask the state machine: "show me events that are applicable for a given state ?" Example of confguration:
public class OfcProjectVersionSMConfiguration extends EnumStateMachineConfigurerAdapter<OfcProjectVersionStates, OfcProjectVersionEvents>
....
public void configure(StateMachineTransitionConfigurer<OfcProjectVersionStates, OfcProjectVersionEvents> transitions) throws Exception {
transitions
.withExternal().source(OfcProjectVersionStates.DRAFT).target(OfcProjectVersionStates.DRAFT).event(OfcProjectVersionEvents.U)
.and()
.withExternal().source(OfcProjectVersionStates.DRAFT).target(OfcProjectVersionStates.DELETED).event(OfcProjectVersionEvents.D)
....
Upvotes: 0
Views: 908
Reputation: 2646
Unfortunately we don't have any reliable ways to know if machine in a particular state would be applicable to process/accept a certain events. Having events as enums you'd know possible possible values but then if events are strings you have infinite list of possible values unless you store those externally in a list.
It gets even more complicated if you have deep nested hierarchical states where you may have different events and if lowest active state don't accept event its then offered to its parent state and so on.
Trouble is that there may be guards doing dynamic evaluations and asking a question of what events machine would accept is like predicting what machine will do in a future.
Upvotes: 0
Reputation: 616
I found out that this would work, but not sure is this the right way.
public abstract class GenericEnumStateMachineUtils extends StateMachineUtils {
public static <S, E> Collection<E> findEventsForState(StateMachine<S, E> stateMachine, S state) {
Collection<E> eventsForState = stateMachine.getTransitions().stream().filter(p -> p.getSource().getId().equals(state)).map(p -> p.getTrigger().getEvent()).collect(Collectors.toCollection(ArrayList::new));
return eventsForState;
}
Upvotes: 1