Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 为状态机增加获取targetState、targetStateChain功能 #518

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ public interface State<S,E,C> extends Visitable{

List<Transition<S,E,C>> getEventTransitions(E event);

List<Transition<S,E,C>> getEventTransitions(E event, TransitionType transitionType);

Collection<Transition<S,E,C>> getAllTransitions();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.alibaba.cola.statemachine;

import java.util.List;

/**
* StateChain
*
* @author benym
* @date 2024/6/11 23:15
*/
public interface StateChain<S, E> extends StateChainVisitable {

/**
* Gets the source state of stateChain
*
* @return the source state
*/
S getSource();

/**
* Gets the list of target states for stateChain
*
* @return the list of target states
*/
List<S> getTargets();

/**
* Gets the event of stateChain
*
* @return event
*/
E getEvent();

/**
* Print stateChain from the console
*/
void showStateChain();

/**
* Generate the plantUml diagram of stateChain
*
* @return String
*/
String generatePlantUml();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.alibaba.cola.statemachine;

/**
* StateChainVisitable
*
* @author benym
* @date 2024/6/12 18:07
*/
public interface StateChainVisitable {

/**
* accept StateChainVisitor and return visitor result
*
* @param visitor StateChainVisitor
* @return String
*/
String accept(final StateChainVisitor visitor);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.alibaba.cola.statemachine;

import java.util.List;

/**
* StateChainVisitor
*
* @author benym
* @date 2024/6/12 18:06
*/
public interface StateChainVisitor {

/**
* @param visitable the element to be visited.
* @return String
*/
String visitOnEntry(StateChain<?, ?> visitable);

/**
* @param visitable the element to be visited.
* @return String
*/
String visitOnExit(StateChain<?, ?> visitable);

/**
* @param chainStateList the element to be visited.
* @param event event
* @return String
*/
<S, C, E> String visitOnStateChain(List<State<S,E,C>> chainStateList, E event);
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,38 @@ public interface StateMachine<S, E, C> extends Visitable{
*/
boolean verify(S sourceStateId,E event);

/**
* Sending an event {@code E} to the state machine
* Calculate the subsequent states of the current sourceState in advance
* This method does not actually perform state transitions
* Such as a given state machine
* STATE1 --> STATE1 : EVENT1
* STATE1 --> STATE2 : EVENT1
* When the method's sourceState is STATE1 and event is EVENT1
* Will return Source: STATE1, Targets: [STATE1, STATE2], Event: EVENT1
*
* @param sourceState the source state
* @param event the event to send
* @return the target state list
*/
List<S> getTargetStates(S sourceState, E event);

/**
* Sending an event {@code E} to the state machine
* Calculate the subsequent state chain of the current sourceState in advance
* This method does not actually perform state transitions
* Such as a given state machine
* STATE1 --> STATE2 : EVENT1
* STATE2 --> STATE3 : EVENT1
* When the method's sourceState is STATE1 and event is EVENT1
* Will return Source: STATE1, Targets: [STATE2, STATE3], Event: EVENT1
*
* @param sourceState the source state
* @param event the event to send
* @return the target state chain list
*/
List<StateChain<S, E>> getTargetStateChain(S sourceState, E event);

/**
* Send an event {@code E} to the state machine.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public interface Transition<S, E, C>{
void setEvent(E event);

void setType(TransitionType type);

TransitionType getType();
/**
* Gets the target state of this transition.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
package com.alibaba.cola.statemachine.impl;

import com.alibaba.cola.statemachine.State;
import com.alibaba.cola.statemachine.StateMachine;
import com.alibaba.cola.statemachine.Transition;
import com.alibaba.cola.statemachine.Visitor;
import com.alibaba.cola.statemachine.*;

import java.util.List;

/**
* PlantUMLVisitor
*
* @author Frank Zhang
* @date 2020-02-09 7:47 PM
*/
public class PlantUMLVisitor implements Visitor {
public class PlantUMLVisitor implements Visitor, StateChainVisitor {

/**
* Since the state machine is stateless, there is no initial state.
Expand All @@ -32,6 +31,30 @@ public String visitOnExit(StateMachine<?, ?, ?> visitable) {
return "@enduml";
}

@Override
public String visitOnEntry(StateChain<?, ?> visitable) {
return "@startuml" + LF;
}

@Override
public String visitOnExit(StateChain<?, ?> visitable) {
return "@enduml";
}

@Override
public <S, C, E> String visitOnStateChain(List<State<S, E, C>> chainStateList, E event) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < chainStateList.size() - 1; i++) {
sb.append(chainStateList.get(i).getId())
.append("->")
.append(chainStateList.get(i + 1).getId())
.append(": ")
.append(event)
.append(LF);
}
return sb.toString();
}

@Override
public String visitOnEntry(State<?, ?, ?> state) {
StringBuilder sb = new StringBuilder();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.alibaba.cola.statemachine.impl;

import com.alibaba.cola.statemachine.State;
import com.alibaba.cola.statemachine.StateChain;
import com.alibaba.cola.statemachine.StateChainVisitor;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
* StateChainImpl
*
* @author benym
* @date 2024/6/12 0:04
*/
public class StateChainImpl<S, E, C> implements StateChain<S, E> {

private final State<S, E, C> sourceState;

private final E event;

private final List<State<S, E, C>> targetStates;

public StateChainImpl(State<S, E, C> sourceState, E event, List<State<S, E, C>> targetStates) {
this.sourceState = sourceState;
this.event = event;
this.targetStates = targetStates;
}

@Override
public S getSource() {
return this.sourceState.getId();
}

@Override
public List<S> getTargets() {
return this.targetStates.stream().map(State::getId)
.collect(Collectors.toList());
}

@Override
public E getEvent() {
return this.event;
}

@Override
public void showStateChain() {
SysOutVisitor sysOutVisitor = new SysOutVisitor();
accept(sysOutVisitor);
}

@Override
public String generatePlantUml() {
PlantUMLVisitor plantUmlVisitor = new PlantUMLVisitor();
return accept(plantUmlVisitor);
}

@Override
public String accept(StateChainVisitor visitor) {
StringBuilder sb = new StringBuilder();
sb.append(visitor.visitOnEntry(this));
List<State<S, E, C>> chainStateList = new ArrayList<>();
chainStateList.add(this.sourceState);
chainStateList.addAll(this.targetStates);
String row = visitor.visitOnStateChain(chainStateList, event);
sb.append(row);
sb.append(visitor.visitOnExit(this));
return sb.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
* StateImpl
Expand Down Expand Up @@ -52,6 +53,18 @@ public List<Transition<S, E, C>> getEventTransitions(E event) {
return eventTransitions.get(event);
}

@Override
public List<Transition<S, E, C>> getEventTransitions(E event, TransitionType transitionType) {
List<Transition<S, E, C>> transitionList = this.getEventTransitions(event);
if (transitionList == null || transitionList.isEmpty()) {
Debugger.debug("There is no Transition for " + event);
return new ArrayList<>();
}
return transitionList.stream()
.filter(transition-> transition.getType().equals(transitionType))
.collect(Collectors.toList());
}

@Override
public Collection<Transition<S, E, C>> getAllTransitions() {
return eventTransitions.allTransitions();
Expand Down
Loading