com.cmt.statemachine.impl.TransitionImpl Maven / Gradle / Ivy
The newest version!
package com.cmt.statemachine.impl;
import com.cmt.statemachine.*;
/**
* TransitionImpl。
*
* This should be designed to be immutable, so that there is no thread-safe risk
*
* @author Frank Zhang
* @date 2020-02-07 10:32 PM
*/
public class TransitionImpl implements Transition {
private State source;
private State target;
private E event;
private Condition> condition;
private String conditionDesc;
private Action,?> action;
private TransitionType type = TransitionType.EXTERNAL;
@Override
public State getSource() {
return source;
}
@Override
public void setSource(State state) {
this.source = state;
}
@Override
public E getEvent() {
return this.event;
}
@Override
public void setEvent(E event) {
this.event = event;
}
@Override
public void setType(TransitionType type) {
this.type = type;
}
@Override
public State getTarget() {
return this.target;
}
@Override
public void setTarget(State target) {
this.target = target;
}
@Override
public Condition> getCondition() {
return this.condition;
}
@Override
public void setCondition(Condition condition) {
this.condition = condition;
}
@Override
public void setCondition(Condition condition, String conditionDesc) {
this.condition = condition;
this.conditionDesc = conditionDesc;
}
@Override
public Action getAction() {
return (Action) this.action;
}
@Override
public void setAction(Action action) {
this.action = action;
}
@Override
public State transit(C request) {
Debugger.debug("Do transition: "+this);
this.verify();
Condition cond = (Condition) condition;
Action ac = (Action) action;
if(cond == null || cond.isSatisfied(request)){
setNextState(target,request);
if(ac != null){
ac.execute(request);
}
return target;
}
Debugger.debug("Condition is not satisfied, stay at the "+source+" state ");
setNextState(source,request);
return source;
}
@Override
public T transitWithResult(C request) {
Debugger.debug("Do transition: "+this);
this.verify();
Condition cond = (Condition) condition;
Action ac = (Action) action;
return nullIfNotSatisfied(cond,request,ac,request);
}
@Override
public final String toString() {
return source + "-[" + event.toString() +", "+type+"]->" + target;
}
@Override
public boolean equals(Object anObject){
if(anObject instanceof Transition){
Transition other = (Transition)anObject;
if(this.event.equals(other.getEvent())
&& this.source.equals(other.getSource())
&& this.target.equals(other.getTarget())){
return true;
}
}
return false;
}
@Override
public void verify() {
if(type== TransitionType.INTERNAL && source != target) {
throw new StateMachineException(String.format("Internal transition source state '%s' " +
"and target state '%s' must be same.", source, target));
}
}
@Override
public T transitWithResult(C cond, R request) {
Debugger.debug("Do transition: "+this);
this.verify();
Condition func = (Condition) condition;
Action ac = (Action) action;
return nullIfNotSatisfied(func,cond,ac,request);
}
@Override
public String getConditionDesc() {
return conditionDesc;
}
private T nullIfNotSatisfied(Condition func, C cond, Action ac, R request) {
if(func == null || func.isSatisfied(cond)){
T t = null;
setNextState(target,request);
if(ac != null){
t = ac.execute(request);
}
return t;
}
setNextState(source,request);
return null;
}
private void setNextState(State s, C request){
if(request instanceof StateAware){
((StateAware) request).setNextState(s.getId());
}
}
}