diff options
Diffstat (limited to 'plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/fsm/StateMachine.java')
-rw-r--r-- | plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/fsm/StateMachine.java | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/fsm/StateMachine.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/fsm/StateMachine.java new file mode 100644 index 0000000000..2f5e991122 --- /dev/null +++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/fsm/StateMachine.java @@ -0,0 +1,149 @@ +package org.eclipse.net4j.util.fsm; + + +import org.apache.log4j.Logger; + + +public abstract class StateMachine<SUBJECT> implements IStateMachine<SUBJECT> +{ + private static final Logger logger = Logger.getLogger(StateMachine.class.getName()); + + private String[] stateNames; + + private String[] eventNames; + + private ITransition<SUBJECT>[][] matrix; + + public StateMachine(String[] stateNames, String[] eventNames, + ITransition<SUBJECT> defaultTransition) + { + this.stateNames = stateNames; + this.eventNames = eventNames; + + matrix = new ITransition[stateNames.length][eventNames.length]; + + if (defaultTransition != null) + { + for (int state = 0; state < stateNames.length; state++) + { + for (int event = 0; event < eventNames.length; event++) + { + handle(state, event, defaultTransition); + } + } + } + } + + public StateMachine(String[] stateNames, String[] eventNames) + { + this(stateNames, eventNames, null); + } + + public int getStateCount() + { + return stateNames.length; + } + + public int getEventCount() + { + return eventNames.length; + } + + public String getStateName(int state) + { + return stateNames[state]; + } + + public String getEventName(int event) + { + return eventNames[event]; + } + + public ITransition<SUBJECT> getIdentityTransition() + { + return new ITransition<SUBJECT>() + { + public void process(SUBJECT subject, int event, Object data) throws Exception + { + if (getLogger().isDebugEnabled()) + { + int state = getState(subject); + getLogger().debug("Ignoring " + makeLabel(subject, state, event)); + } + } + }; + } + + public void handle(int state, int event, ITransition<SUBJECT> transition) + { + matrix[state][event] = transition; + } + + public void handle(int state, int event, final int newState) + { + handle(state, event, new ITransition<SUBJECT>() + { + public void process(SUBJECT subject, int event, Object data) throws Exception + { + setState(subject, newState); + } + }); + } + + public void ignore(int state, int event) + { + handle(state, event, getIdentityTransition()); + } + + public void cancel(int state, int event) + { + handle(state, event, null); + } + + public void process(SUBJECT subject, int event, Object data) throws Exception + { + int state = getState(subject); + ITransition<SUBJECT> transition = matrix[state][event]; + + if (transition == null) + { + if (getLogger().isDebugEnabled()) + { + getLogger().warn("Ignoring " + makeLabel(subject, state, event)); + } + + return; + } + + if (getLogger().isDebugEnabled()) + { + getLogger().debug("Processing " + makeLabel(subject, state, event)); + } + + transition.process(subject, event, data); + + if (getLogger().isDebugEnabled()) + { + int newState = getState(subject); + getLogger() + .debug( + "Finished " + makeLabel(subject, state, event) + ", newState=" + + getStateName(newState)); + } + } + + protected Logger getLogger() + { + return logger; + } + + protected String makeLabel(SUBJECT subject, int state, int event) + { + return "event " + eventNames[event] + " in state " + stateNames[state] + " for subject " + + subject; + } + + protected abstract int getState(SUBJECT subject); + + protected abstract void setState(SUBJECT subject, int state); +}
\ No newline at end of file |