Skip to content

Commit

Permalink
add statemachine
Browse files Browse the repository at this point in the history
  • Loading branch information
fulan.zjf committed Feb 10, 2020
1 parent bc57c0f commit f696802
Show file tree
Hide file tree
Showing 35 changed files with 1,577 additions and 1 deletion.
53 changes: 53 additions & 0 deletions cola-statemachine/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.alibaba.cola</groupId>
<artifactId>statemachine</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>

<dependencies>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.9</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.22</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.alibaba.cola.statemachine;

/**
* Generic strategy interface used by a state machine to respond
* events by executing an {@code Action} with a {@link StateContext}.
*
* @author Frank Zhang
* @date 2020-02-07 2:51 PM
*/
public interface Action<S, E, C> {

// /**
// * Execute action with a {@link StateContext}.
// *
// * @param context the state context
// */
// void execute(StateContext<S, E> context);

public void execute(S from, S to, E event, C context);

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

/**
* Condition
*
* @author Frank Zhang
* @date 2020-02-07 2:50 PM
*/
public interface Condition<C> {

/**
* @param context context object
* @return whether the context satisfied current condition
*/
boolean isSatisfied(C context);

default String name(){
return this.getClass().getSimpleName();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.alibaba.cola.statemachine;

import com.alibaba.cola.statemachine.impl.TransitionType;

import java.util.Collection;
import java.util.Optional;

/**
* State
*
* @param <S> the type of state
* @param <E> the type of event
*
* @author Frank Zhang
* @date 2020-02-07 2:12 PM
*/
public interface State<S,E,C> extends Visitable{

/**
* Gets the state identifier.
*
* @return the state identifiers
*/
S getId();

/**
* Add transition to the state
* @param event the event of the Transition
* @param target the target of the transition
* @return
*/
Transition<S,E,C> addTransition(E event, State<S, E, C> target, TransitionType transitionType);

Optional<Transition<S,E,C>> getTransition(E event);

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

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

/**
* StateContext
*
* @author Frank Zhang
* @date 2020-02-07 2:49 PM
*/
public interface StateContext<S, E, C> {
/**
* Gets the transition.
*
* @return the transition
*/
Transition<S, E, C> getTransition();

/**
* Gets the state machine.
*
* @return the state machine
*/
StateMachine<S, E, C> getStateMachine();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.alibaba.cola.statemachine;

/**
* StateMachine
*
* @author Frank Zhang
*
* @param <S> the type of state
* @param <E> the type of event
* @param <C> the user defined context
* @date 2020-02-07 2:13 PM
*/
public interface StateMachine<S, E, C> extends Visitable{

/**
* Send an event {@code E} to the state machine.
*
* @param sourceState the source state
* @param event the event to send
* @param ctx the user defined context
* @return the target state
*/
S fireEvent(S sourceState, E event, C ctx);

/**
* MachineId is the identifier for a State Machine
* @return
*/
String getMachineId();

/**
* Use visitor pattern to display the structure of the state machine
*/
void showStateMachine();

void generatePlantUML();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.alibaba.cola.statemachine;

import com.alibaba.cola.statemachine.impl.StateMachineException;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
* StateMachineFactory
*
* @author Frank Zhang
* @date 2020-02-08 10:21 PM
*/
public class StateMachineFactory {
static Map<String /* machineId */, StateMachine> stateMachineMap = new ConcurrentHashMap<>();

public static void register(StateMachine stateMachine){
String machineId = stateMachine.getMachineId();
if(stateMachineMap.get(machineId) != null){
throw new StateMachineException("The state machine with id ["+machineId+"] is already built, no need to build again");
}
stateMachineMap.put(stateMachine.getMachineId(), stateMachine);
}

public static StateMachine get(String machineId){
StateMachine stateMachine = stateMachineMap.get(machineId);
if(stateMachine == null){
throw new StateMachineException("There is no stateMachine instance for "+machineId+", please build it first");
}
return stateMachine;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.alibaba.cola.statemachine;

import com.alibaba.cola.statemachine.impl.TransitionType;

/**
* {@code Transition} is something what a state machine associates with a state
* changes.
*
* @author Frank Zhang
*
* @param <S> the type of state
* @param <E> the type of event
* @param <C> the type of user defined context, which is used to hold application data
*
* @date 2020-02-07 2:20 PM
*/
public interface Transition<S, E, C>{
/**
* Gets the source state of this transition.
*
* @return the source state
*/
State<S,E,C> getSource();

void setSource(State<S, E, C> state);

E getEvent();

void setEvent(E event);

void setType(TransitionType type);
/**
* Gets the target state of this transition.
*
* @return the target state
*/
State<S,E,C> getTarget();

void setTarget(State<S, E, C> state);

/**
* Gets the guard of this transition.
*
* @return the guard
*/
Condition<C> getCondition();

void setCondition(Condition<C> condition);

Action<S,E,C> getAction();

void setAction(Action<S, E, C> action);

/**
* Do transition from source state to target state.
*
* @return the target state
*/

State<S,E,C> transit(C ctx);
/**
* Verify transition correctness
*/
void verify();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.alibaba.cola.statemachine;

/**
* Visitable
*
* @author Frank Zhang
* @date 2020-02-08 8:41 PM
*/
public interface Visitable {
void accept(final Visitor visitor);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.alibaba.cola.statemachine;

/**
* Visitor
*
* @author Frank Zhang
* @date 2020-02-08 8:41 PM
*/
public interface Visitor {
/**
* @param visitable the element to be visited.
*/
void visitOnEntry(StateMachine<?, ?, ?> visitable);

/**
* @param visitable the element to be visited.
*/
void visitOnExit(StateMachine<?, ?, ?> visitable);

/**
* @param visitable the element to be visited.
*/
void visitOnEntry(State<?, ?, ?> visitable);

/**
* @param visitable the element to be visited.
*/
void visitOnExit(State<?, ?, ?> visitable);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.alibaba.cola.statemachine.builder;

/**
* ExternalTransitionBuilder
*
* @author Frank Zhang
* @date 2020-02-07 6:11 PM
*/
public interface ExternalTransitionBuilder<S, E, C> {
/**
* Build transition source state.
* @param stateId id of state
* @return from clause builder
*/
From<S, E, C> from(S stateId);

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

/**
* ExternalTransitionsBuilder
*
* This builder is for multiple transitions, currently only support multiple sources <----> one target
*
* @author Frank Zhang
* @date 2020-02-08 7:41 PM
*/
public interface ExternalTransitionsBuilder<S, E, C> {
From<S, E, C> fromAmong(S... stateIds);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.alibaba.cola.statemachine.builder;

/**
* From
*
* @author Frank Zhang
* @date 2020-02-07 6:13 PM
*/
public interface From<S, E, C> {
/**
* Build transition target state and return to clause builder
* @param stateId id of state
* @return To clause builder
*/
To<S, E, C> to(S stateId);

}
Loading

0 comments on commit f696802

Please sign in to comment.