summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEike Stepper2007-07-22 01:41:30 (EDT)
committerEike Stepper2007-07-22 01:41:30 (EDT)
commit94c1da16f0bb880f1c981e6b5d4b3a43462e3dcf (patch)
treee381b5559f56ba8a3d5dd10df86a0d6586e9e90e
parentfaca69994df1ace5c58695a861d50e6db0d09069 (diff)
downloadcdo-94c1da16f0bb880f1c981e6b5d4b3a43462e3dcf.zip
cdo-94c1da16f0bb880f1c981e6b5d4b3a43462e3dcf.tar.gz
cdo-94c1da16f0bb880f1c981e6b5d4b3a43462e3dcf.tar.bz2
*** empty log message ***
-rw-r--r--plugins/org.eclipse.net4j.util/META-INF/MANIFEST.MF2
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/fsm/FiniteStateMachine.java197
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/fsm/ITransition.java19
3 files changed, 218 insertions, 0 deletions
diff --git a/plugins/org.eclipse.net4j.util/META-INF/MANIFEST.MF b/plugins/org.eclipse.net4j.util/META-INF/MANIFEST.MF
index 33b8887..ae3a184 100644
--- a/plugins/org.eclipse.net4j.util/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.net4j.util/META-INF/MANIFEST.MF
@@ -12,6 +12,7 @@ Import-Package: org.eclipse.core.runtime;resolution:=optional,
org.osgi.service.log;version="1.3.0";resolution:=optional,
org.osgi.util.tracker;version="1.3.0";resolution:=optional
Export-Package: org.eclipse.net4j.internal.util;version="0.8.0",
+ org.eclipse.net4j.internal.util.bundle,
org.eclipse.net4j.internal.util.collection;version="0.8.0",
org.eclipse.net4j.internal.util.concurrent;version="0.8.0",
org.eclipse.net4j.internal.util.container;version="0.8.0",
@@ -32,6 +33,7 @@ Export-Package: org.eclipse.net4j.internal.util;version="0.8.0",
org.eclipse.net4j.util.container.delegate;version="0.8.0",
org.eclipse.net4j.util.event;version="0.8.0",
org.eclipse.net4j.util.factory;version="0.8.0",
+ org.eclipse.net4j.util.fsm;version="0.8.0",
org.eclipse.net4j.util.io;version="0.8.0",
org.eclipse.net4j.util.lifecycle;version="0.8.0",
org.eclipse.net4j.util.om;version="0.8.0",
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/fsm/FiniteStateMachine.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/fsm/FiniteStateMachine.java
new file mode 100644
index 0000000..76119f6
--- /dev/null
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/fsm/FiniteStateMachine.java
@@ -0,0 +1,197 @@
+package org.eclipse.net4j.util.fsm;
+
+import org.eclipse.net4j.internal.util.bundle.OM;
+import org.eclipse.net4j.internal.util.om.trace.ContextTracer;
+
+import java.text.MessageFormat;
+
+/**
+ * @author Eike Stepper
+ */
+public abstract class FiniteStateMachine<STATE extends Enum, EVENT extends Enum, SUBJECT>
+{
+ public static final ITransition IGNORE = new IgnoreTransition();
+
+ public static final ITransition FAIL = new FailTransition();
+
+ private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, FiniteStateMachine.class);
+
+ private static final String MSG_PROCESS = "Processing event {0} in state {1} for {2} (data={3})";
+
+ private static final String MSG_IGNORE = "Ignoring event {0} in state {1} for {2} (data={3})";
+
+ private static final String MSG_FAIL = "Failing event {0} in state {1} for {2} (data={3})";
+
+ private STATE[] states;
+
+ private EVENT[] events;
+
+ private ITransition[][] transitions;
+
+ public FiniteStateMachine(Class<STATE> stateEnum, Class<EVENT> eventEnum, ITransition defaultTransition)
+ {
+ states = stateEnum.getEnumConstants();
+ events = eventEnum.getEnumConstants();
+ transitions = new ITransition[states.length][events.length];
+ transitAll(defaultTransition);
+ }
+
+ public FiniteStateMachine(Class<STATE> stateEnum, Class<EVENT> eventEnum)
+ {
+ this(stateEnum, eventEnum, IGNORE);
+ }
+
+ public final STATE[] getStates()
+ {
+ return states;
+ }
+
+ public final EVENT[] getEvents()
+ {
+ return events;
+ }
+
+ public final ITransition getTransition(STATE state, EVENT event)
+ {
+ int s = state.ordinal();
+ int e = event.ordinal();
+ return transitions[s][e];
+ }
+
+ public final void transit(STATE state, EVENT event, ITransition transition)
+ {
+ checkTransition(transition);
+ int s = state.ordinal();
+ int e = event.ordinal();
+ transitions[s][e] = transition;
+ }
+
+ public final void transitEvents(STATE state, ITransition transition)
+ {
+ checkTransition(transition);
+ int s = state.ordinal();
+ for (int e = 0; e < events.length; e++)
+ {
+ transitions[s][e] = transition;
+ }
+ }
+
+ public final void transitStates(EVENT event, ITransition transition)
+ {
+ checkTransition(transition);
+ int e = event.ordinal();
+ for (int s = 0; s < states.length; s++)
+ {
+ transitions[s][e] = transition;
+ }
+ }
+
+ public final void transitAll(ITransition transition)
+ {
+ checkTransition(transition);
+ for (int s = 0; s < states.length; s++)
+ {
+ for (int e = 0; e < events.length; e++)
+ {
+ transitions[s][e] = transition;
+ }
+ }
+ }
+
+ public final <DATA> void process(SUBJECT subject, EVENT event, DATA data)
+ {
+ STATE state = getState(subject);
+ int s = state.ordinal();
+ int e = event.ordinal();
+ ITransition transition = transitions[s][e];
+ if (transition == IGNORE)
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.trace(formatIgnoreMessage(subject, state, event, data));
+ }
+ }
+ else if (transition == FAIL)
+ {
+ throw new IllegalStateException(formatFailMessage(subject, state, event, data));
+ }
+ else
+ {
+ if (TRACER.isEnabled())
+ {
+ TRACER.trace(formatProcessMessage(subject, state, event, data));
+ }
+
+ transition.execute(subject, state, event, data);
+ }
+ }
+
+ protected ITransition createIgnoreTransition(STATE state, EVENT event)
+ {
+ return IGNORE;
+ }
+
+ protected ITransition createFailTransition(STATE state, EVENT event)
+ {
+ return FAIL;
+ }
+
+ protected String formatProcessMessage(SUBJECT subject, STATE state, EVENT event, Object data)
+ {
+ return MessageFormat.format(MSG_PROCESS, event, state, subject, data);
+ }
+
+ protected String formatIgnoreMessage(SUBJECT subject, STATE state, EVENT event, Object data)
+ {
+ return MessageFormat.format(MSG_IGNORE, event, state, subject, data);
+ }
+
+ protected String formatFailMessage(SUBJECT subject, STATE state, EVENT event, Object data)
+ {
+ return MessageFormat.format(MSG_FAIL, event, state, subject, data);
+ }
+
+ protected abstract STATE getState(SUBJECT subject);
+
+ private void checkTransition(ITransition transition)
+ {
+ if (transition == null)
+ {
+ throw new IllegalArgumentException("transition == null");
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ public static class IgnoreTransition implements ITransition
+ {
+ public void execute(Object subject, Enum state, Enum event, Object data)
+ {
+ // Do nothing
+ }
+
+ @Override
+ public String toString()
+ {
+ return "IGNORE";
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ public static class FailTransition implements ITransition
+ {
+ public void execute(Object subject, Enum state, Enum event, Object data)
+ {
+ // Do nothing
+ }
+
+ @Override
+ public String toString()
+ {
+ return "FAIL";
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/fsm/ITransition.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/fsm/ITransition.java
new file mode 100644
index 0000000..059337b
--- /dev/null
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/fsm/ITransition.java
@@ -0,0 +1,19 @@
+/***************************************************************************
+ * Copyright (c) 2004 - 2007 Eike Stepper, Germany.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ **************************************************************************/
+package org.eclipse.net4j.util.fsm;
+
+/**
+ * @author Eike Stepper
+ */
+public interface ITransition<STATE extends Enum, EVENT extends Enum, SUBJECT, DATA>
+{
+ public void execute(SUBJECT subject, STATE state, EVENT event, DATA data);
+}