You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by ra...@apache.org on 2006/03/01 05:50:55 UTC

svn commit: r381905 - /jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/AbstractStateMachine.java

Author: rahul
Date: Tue Feb 28 20:50:53 2006
New Revision: 381905

URL: http://svn.apache.org/viewcvs?rev=381905&view=rev
Log:
The AbstractStateMachine class demonstrates one approach for providing the base functionality needed by classes representing stateful entities, whose behaviors are defined via SCXML documents.

Added:
    jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/AbstractStateMachine.java   (with props)

Added: jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/AbstractStateMachine.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/AbstractStateMachine.java?rev=381905&view=auto
==============================================================================
--- jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/AbstractStateMachine.java (added)
+++ jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/AbstractStateMachine.java Tue Feb 28 20:50:53 2006
@@ -0,0 +1,295 @@
+/*
+ *
+ *   Copyright 2006 The Apache Software Foundation.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+package org.apache.commons.scxml.env;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URL;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.scxml.Context;
+import org.apache.commons.scxml.Evaluator;
+import org.apache.commons.scxml.SCXMLExecutor;
+import org.apache.commons.scxml.SCXMLListener;
+import org.apache.commons.scxml.TriggerEvent;
+import org.apache.commons.scxml.env.jexl.JexlContext;
+import org.apache.commons.scxml.env.jexl.JexlEvaluator;
+import org.apache.commons.scxml.io.SCXMLDigester;
+import org.apache.commons.scxml.model.ModelException;
+import org.apache.commons.scxml.model.SCXML;
+import org.apache.commons.scxml.model.Transition;
+import org.apache.commons.scxml.model.TransitionTarget;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * This class demonstrates one approach for providing the base
+ * functionality needed by classes representing stateful entities,
+ * whose behaviors are defined via SCXML documents.
+ *
+ * SCXML documents (more generically, UML state chart diagrams) can be
+ * used to define stateful behavior of objects, and Commons SCXML enables
+ * developers to use this model directly into the corresponding code
+ * artifacts. The resulting artifacts tend to be much simpler, embody
+ * a useful separation of concerns and are easier to understand and
+ * maintain. As the size of the modeled entity grows, these benefits
+ * become more apparent.
+ *
+ * This approach functions by registering an SCXMLListener that gets
+ * notified onentry, and calls the namesake method for each state that
+ * has been entered.
+ *
+ * This class swallows all exceptions only to log them. Developers of
+ * subclasses should think of themselves as "component developers"
+ * catering to other end users, and therefore ensure that the subclasses
+ * are free of <code>ModelException</code>s and the like. Most methods
+ * are <code>protected</code> for ease of subclassing.
+ *
+ */
+public abstract class AbstractStateMachine {
+
+    /**
+     * The state machine that will drive the instances of this class.
+     */
+    private static SCXML stateMachine;
+
+    /**
+     * The instance specific SCXML engine.
+     */
+    private SCXMLExecutor engine;
+
+    /**
+     * The log.
+     */
+    private Log log;
+
+    /**
+     * The method signature for the activities corresponding to each
+     * state in the SCXML document.
+     */
+    private static final Class[] SIGNATURE = new Class[0];
+
+    /**
+     * The method parameters for the activities corresponding to each
+     * state in the SCXML document.
+     */
+    private static final Object[] PARAMETERS = new Object[0];
+
+    /**
+     * Convenience constructor.
+     *
+     * @param scxmlDocument The URL pointing to the SCXML document that
+     *                      describes the &quot;lifecycle&quot; of the
+     *                      instances of this class.
+     */
+    public AbstractStateMachine(final URL scxmlDocument) {
+        // default is JEXL
+        this(scxmlDocument, new JexlContext(), new JexlEvaluator());
+    }
+
+    /**
+     * Primary constructor.
+     *
+     * @param scxmlDocument The URL pointing to the SCXML document that
+     *                      describes the &quot;lifecycle&quot; of the
+     *                      instances of this class.
+     * @param rootCtx The root context for this instance.
+     * @param evaluator The expression evaluator for this instance.
+     *
+     * @see Context
+     * @see Evaluator
+     */
+    public AbstractStateMachine(final URL scxmlDocument,
+            final Context rootCtx, final Evaluator evaluator) {
+        log = LogFactory.getLog(this.getClass());
+        if (stateMachine == null) {
+            // parse only once per subclass
+            ErrorHandler errHandler = new SimpleErrorHandler();
+            try {
+                stateMachine = SCXMLDigester.digest(scxmlDocument,
+                    errHandler);
+            } catch (IOException ioe) {
+                logError(ioe);
+            } catch (SAXException sae) {
+                logError(sae);
+            }
+        }
+        engine = new SCXMLExecutor(evaluator, new SimpleDispatcher(),
+            new SimpleErrorReporter());
+        engine.setStateMachine(stateMachine);
+        engine.setSuperStep(true);
+        engine.setRootContext(rootCtx);
+        engine.addListener(stateMachine, new EntryListener());
+        try {
+            engine.go();
+        } catch (ModelException me) {
+            logError(me);
+        }
+    }
+
+    /**
+     * Fire an event on the SCXML engine.
+     *
+     * @param event The event name.
+     * @return Whether the state machine has reached a &quot;final&quot;
+     *         configuration.
+     */
+    public boolean fireEvent(final String event) {
+        TriggerEvent[] evts = {new TriggerEvent(event,
+                TriggerEvent.SIGNAL_EVENT, null)};
+        try {
+            engine.triggerEvents(evts);
+        } catch (ModelException me) {
+            logError(me);
+        }
+        return engine.getCurrentStatus().isFinal();
+    }
+
+    /**
+     * Get the SCXML object representing this state machine.
+     *
+     * @return Returns the stateMachine.
+     */
+    public static SCXML getStateMachine() {
+        return stateMachine;
+    }
+
+    /**
+     * Get the SCXML engine driving the &quot;lifecycle&quot; of the
+     * instances of this class.
+     *
+     * @return Returns the engine.
+     */
+    public SCXMLExecutor getEngine() {
+        return engine;
+    }
+
+    /**
+     * Get the log for this class.
+     *
+     * @return Returns the log.
+     */
+    public Log getLog() {
+        return log;
+    }
+
+    /**
+     * Set the log for this class.
+     *
+     * @param log The log to set.
+     */
+    public void setLog(final Log log) {
+        this.log = log;
+    }
+
+    /**
+     * Invoke the no argument method with the following name.
+     *
+     * @param methodName The method to invoke.
+     * @return Whether the invoke was successful.
+     */
+    public boolean invoke(final String methodName) {
+        Class clas = this.getClass();
+        try {
+            Method method = clas.getDeclaredMethod(methodName, SIGNATURE);
+            method.invoke(this, PARAMETERS);
+        } catch (SecurityException se) {
+            logError(se);
+            return false;
+        } catch (NoSuchMethodException nsme) {
+            logError(nsme);
+            return false;
+        } catch (IllegalArgumentException iae) {
+            logError(iae);
+            return false;
+        } catch (IllegalAccessException iae) {
+            logError(iae);
+            return false;
+        } catch (InvocationTargetException ite) {
+            logError(ite);
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Reset the state machine.
+     *
+     * @return Whether the reset was successful.
+     */
+    public boolean resetMachine() {
+        try {
+            engine.reset();
+        } catch (ModelException me) {
+            logError(me);
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Utility method for logging error.
+     *
+     * @param exception The exception leading to this error condition.
+     */
+    protected void logError(final Exception exception) {
+        if (log.isErrorEnabled()) {
+            log.error(exception.getMessage(), exception);
+        }
+    }
+
+    /**
+     * A SCXMLListener that is only concerned about &quot;onentry&quot;
+     * notifications.
+     */
+    protected class EntryListener implements SCXMLListener {
+
+        /**
+         * {@inheritDoc}
+         */
+        public void onEntry(final TransitionTarget entered) {
+            invoke(entered.getId());
+        }
+
+        /**
+         * No-op.
+         *
+         * @param from The &quot;source&quot; transition target.
+         * @param to The &quot;destination&quot; transition target.
+         * @param transition The transition being followed.
+         */
+        public void onTransition(final TransitionTarget from,
+                final TransitionTarget to, final Transition transition) {
+            // nothing to do
+        }
+
+        /**
+         * No-op.
+         *
+         * @param exited The transition target being exited.
+         */
+        public void onExit(final TransitionTarget exited) {
+            // nothing to do
+        }
+
+    }
+
+}
+

Propchange: jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/AbstractStateMachine.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/commons/sandbox/scxml/trunk/src/main/java/org/apache/commons/scxml/env/AbstractStateMachine.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org