Author: ate Date: Fri Mar 14 00:50:35 2014 New Revision: 1577400 URL: http://svn.apache.org/r1577400 Log: SCXML-196
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLExecutor.java commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLSemantics.java commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/semantics/SCXMLSemanticsImpl.java Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLExecutor.java URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLExecutor.java?rev=1577400&r1=1577399&r2=1577400&view=diff ============================================================================== --- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLExecutor.java (original) +++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLExecutor.java Fri Mar 14 00:50:35 2014 @@ -437,17 +437,12 @@ public class SCXMLExecutor implements Se // CreateEmptyStatus currentStatus = new Status(); Step step = new Step(null, currentStatus); + // execute initial script if defined + semantics.executeGlobalScript(step, stateMachine, eventdispatcher, errorReporter, scInstance); // DetermineInitialStates - semantics.determineInitialStates(stateMachine, - step.getAfterStatus().getStates(), - step.getEntryList(), errorReporter, scInstance); - // execute initial script if defined configured as transition so as to not trigger events - if (stateMachine.getInitialScript() != null) { - step.getTransitList().add((Transition)stateMachine.getInitialScript().getParent()); - } - // ExecuteActions - semantics.executeActions(step, stateMachine, eventdispatcher, - errorReporter, scInstance); + semantics.determineInitialStates(step, stateMachine, errorReporter, scInstance); + // enter initial states + semantics.enterStates(step, stateMachine, eventdispatcher, errorReporter, scInstance); // AssignCurrentStatus updateStatus(step); // Execute Immediate Transitions Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLSemantics.java URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLSemantics.java?rev=1577400&r1=1577399&r2=1577400&view=diff ============================================================================== --- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLSemantics.java (original) +++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLSemantics.java Fri Mar 14 00:50:35 2014 @@ -16,29 +16,18 @@ */ package org.apache.commons.scxml2; -import java.util.List; -import java.util.Set; - import org.apache.commons.scxml2.model.ModelException; import org.apache.commons.scxml2.model.SCXML; -import org.apache.commons.scxml2.model.TransitionTarget; /** - * <p>The purpose of this interface is to separate the interpretation algorithm + * <p>The purpose of this interface is to separate the the + * <a href="http://www.w3.org/TR/2014/CR-scxml-20140313/#AlgorithmforSCXMLInterpretation"> + * W3C SCXML Algorithm for SCXML Interpretation</a> * from the <code>SCXMLExecutor</code> and therefore make it pluggable.</p> * * <p>Semantics agnostic utility functions and common operators as defined in * UML can be found in the <code>SCXMLHelper</code> or attached directly to - * the SCXML model elements. Some of the possible semantic interpretations - * are, for example:</p> - * - * <ul> - * <li>STATEMATE - * <li>RHAPSODY - * <li>ROOMCharts - * <li>UML 1.5 - * <li>UML 2.0 - * </ul> + * the SCXML model elements.</p> * * <p>Specific semantics can be created by subclassing * <code>org.apache.commons.scxml2.semantics.SCXMLSemanticsImpl</code>.</p> @@ -57,15 +46,25 @@ public interface SCXMLSemantics { */ SCXML normalizeStateMachine(final SCXML input, final ErrorReporter errRep); + public void executeGlobalScript(final Step step, final SCXML stateMachine, final EventDispatcher evtDispatcher, + final ErrorReporter errRep, final SCInstance scInstance) throws ModelException; + + public void exitStates(final Step step, final SCXML stateMachine, final EventDispatcher evtDispatcher, + final ErrorReporter errRep, final SCInstance scInstance) throws ModelException; + + public void executeTransitionContent(final Step step, final SCXML stateMachine, final EventDispatcher evtDispatcher, + final ErrorReporter errRep, final SCInstance scInstance) throws ModelException; + + public void enterStates(final Step step, final SCXML stateMachine, final EventDispatcher evtDispatcher, + final ErrorReporter errRep, final SCInstance scInstance) throws ModelException; + /** * Determining the initial state(s) for this state machine. * - * @param input + * @param step + * provides target states and entry list to fill in [out] + * @param stateMachine * SCXML state machine - * @param states - * a set of States to populate - * @param entryList - * a list of States and Parallels to enter * @param errRep * ErrorReporter callback * @param scInstance @@ -74,8 +73,7 @@ public interface SCXMLSemantics { * @throws ModelException * in case there is a fatal SCXML object model problem. */ - void determineInitialStates(final SCXML input, final Set<TransitionTarget> states, - final List<TransitionTarget> entryList, final ErrorReporter errRep, + void determineInitialStates(final Step step, final SCXML stateMachine, final ErrorReporter errRep, final SCInstance scInstance) throws ModelException; @@ -195,6 +193,5 @@ public interface SCXMLSemantics { */ void initiateInvokes(final Step step, final ErrorReporter errRep, final SCInstance scInstance); - } Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/semantics/SCXMLSemanticsImpl.java URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/semantics/SCXMLSemanticsImpl.java?rev=1577400&r1=1577399&r2=1577400&view=diff ============================================================================== --- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/semantics/SCXMLSemanticsImpl.java (original) +++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/semantics/SCXMLSemanticsImpl.java Fri Mar 14 00:50:35 2014 @@ -46,6 +46,7 @@ import org.apache.commons.scxml2.Trigger import org.apache.commons.scxml2.invoke.Invoker; import org.apache.commons.scxml2.invoke.InvokerException; import org.apache.commons.scxml2.model.Action; +import org.apache.commons.scxml2.model.Executable; import org.apache.commons.scxml2.model.Finalize; import org.apache.commons.scxml2.model.History; import org.apache.commons.scxml2.model.Initial; @@ -185,6 +186,19 @@ public class SCXMLSemanticsImpl implemen return false; } + protected void executeContent(Executable exec, final EventDispatcher evtDispatcher, final ErrorReporter errRep, + final SCInstance scInstance, final Collection<TriggerEvent> internalEvents) + throws ModelException { + + try { + for (Action action : exec.getActions()) { + action.execute(evtDispatcher, errRep, scInstance, appLog, internalEvents); + } + } catch (SCXMLExpressionException e) { + errRep.onError(ErrorConstants.EXPRESSION_ERROR, e.getMessage(), exec); + } + } + /** * @param input * SCXML state machine @@ -193,86 +207,32 @@ public class SCXMLSemanticsImpl implemen * ErrorReporter callback */ public SCXML normalizeStateMachine(final SCXML input, - final ErrorReporter errRep) { + final ErrorReporter errRep) { //it is a no-op for now return input; } - /** - * @param input - * SCXML state machine [in] - * @param targets - * a set of initial targets to populate [out] - * @param entryList - * a list of States and Parallels to enter [out] - * @param errRep - * ErrorReporter callback [inout] - * @param scInstance - * The state chart instance [in] - * @throws ModelException - * in case there is a fatal SCXML object model problem. - */ - public void determineInitialStates(final SCXML input, final Set<TransitionTarget> targets, - final List<TransitionTarget> entryList, final ErrorReporter errRep, - final SCInstance scInstance) - throws ModelException { - TransitionTarget tmp = input.getInitialTarget(); - if (tmp == null) { - errRep.onError(ErrorConstants.NO_INITIAL, - "SCXML initialstate is missing!", input); - } else { - targets.add(tmp); - determineTargetStates(targets, errRep, scInstance); - //set of ALL entered states (even if initialState is a jump-over) - Set<TransitionTarget> onEntry = SCXMLHelper.getAncestorClosure(targets, null); - // sort onEntry according state hierarchy - TransitionTarget[] oen = onEntry.toArray(new TransitionTarget[onEntry.size()]); - onEntry.clear(); - Arrays.sort(oen, getTTComparator()); - // we need to impose reverse order for the onEntry list - List<TransitionTarget> entering = Arrays.asList(oen); - Collections.reverse(entering); - entryList.addAll(entering); - + public void executeGlobalScript(final Step step, final SCXML stateMachine, final EventDispatcher evtDispatcher, + final ErrorReporter errRep, final SCInstance scInstance) throws ModelException { + if (stateMachine.getInitialScript() != null) { + try { + stateMachine.getInitialScript().execute(evtDispatcher, errRep, scInstance, appLog, + step.getAfterStatus().getEvents()); + } catch (SCXMLExpressionException e) { + errRep.onError(ErrorConstants.EXPRESSION_ERROR, e.getMessage(), stateMachine); + } } } - /** - * Executes all OnExit/Transition/OnEntry transitional actions. - * - * @param step - * provides EntryList, TransitList, ExitList gets - * updated its AfterStatus/Events - * @param stateMachine - * state machine - SCXML instance - * @param evtDispatcher - * the event dispatcher - EventDispatcher instance - * @param errRep - * error reporter - * @param scInstance - * The state chart instance - * @throws ModelException - * in case there is a fatal SCXML object model problem. - */ - public void executeActions(final Step step, final SCXML stateMachine, - final EventDispatcher evtDispatcher, - final ErrorReporter errRep, final SCInstance scInstance) - throws ModelException { + public void exitStates(final Step step, final SCXML stateMachine, final EventDispatcher evtDispatcher, + final ErrorReporter errRep, final SCInstance scInstance) throws ModelException { NotificationRegistry nr = scInstance.getNotificationRegistry(); Collection<TriggerEvent> internalEvents = step.getAfterStatus().getEvents(); Map<TransitionTarget, Invoker> invokers = scInstance.getInvokers(); // ExecutePhaseActions / OnExit for (TransitionTarget tt : step.getExitList()) { OnExit oe = tt.getOnExit(); - try { - for (Action onExitAct : oe.getActions()) { - onExitAct.execute(evtDispatcher, - errRep, scInstance, appLog, internalEvents); - } - } catch (SCXMLExpressionException e) { - errRep.onError(ErrorConstants.EXPRESSION_ERROR, e.getMessage(), - oe); - } + executeContent(oe, evtDispatcher, errRep, scInstance, internalEvents); // check if invoke is active in this state if (invokers.containsKey(tt)) { Invoker toCancel = invokers.get(tt); @@ -280,7 +240,7 @@ public class SCXMLSemanticsImpl implemen toCancel.cancel(); } catch (InvokerException ie) { TriggerEvent te = new TriggerEvent(tt.getId() - + ".invoke.cancel.failed", TriggerEvent.ERROR_EVENT); + + ".invoke.cancel.failed", TriggerEvent.ERROR_EVENT); internalEvents.add(te); } // done here, don't wait for cancel response @@ -292,35 +252,29 @@ public class SCXMLSemanticsImpl implemen TriggerEvent.CHANGE_EVENT); internalEvents.add(te); } - // ExecutePhaseActions / Transitions + } + + public void executeTransitionContent(final Step step, final SCXML stateMachine, final EventDispatcher evtDispatcher, + final ErrorReporter errRep, final SCInstance scInstance) throws ModelException { + NotificationRegistry nr = scInstance.getNotificationRegistry(); + Collection<TriggerEvent> internalEvents = step.getAfterStatus().getEvents(); for (Transition t : step.getTransitList()) { - try { - for (Action transitAct : t.getActions()) { - transitAct.execute(evtDispatcher, - errRep, scInstance, appLog, internalEvents); - } - } catch (SCXMLExpressionException e) { - errRep.onError(ErrorConstants.EXPRESSION_ERROR, - e.getMessage(), t); - } + executeContent(t, evtDispatcher, errRep, scInstance, internalEvents); List<TransitionTarget> rtargets = t.getRuntimeTargets(); for (TransitionTarget tt : rtargets) { nr.fireOnTransition(t, t.getParent(), tt, t); nr.fireOnTransition(stateMachine, t.getParent(), tt, t); } } - // ExecutePhaseActions / OnEntry + } + + public void enterStates(final Step step, final SCXML stateMachine, final EventDispatcher evtDispatcher, + final ErrorReporter errRep, final SCInstance scInstance) throws ModelException { + NotificationRegistry nr = scInstance.getNotificationRegistry(); + Collection<TriggerEvent> internalEvents = step.getAfterStatus().getEvents(); for (TransitionTarget tt : step.getEntryList()) { OnEntry oe = tt.getOnEntry(); - try { - for (Action onEntryAct : oe.getActions()) { - onEntryAct.execute(evtDispatcher, - errRep, scInstance, appLog, internalEvents); - } - } catch (SCXMLExpressionException e) { - errRep.onError(ErrorConstants.EXPRESSION_ERROR, e.getMessage(), - oe); - } + executeContent(oe, evtDispatcher, errRep, scInstance, internalEvents); nr.fireOnEntry(tt, tt); nr.fireOnEntry(stateMachine, tt); TriggerEvent te = new TriggerEvent(tt.getId() + ".entry", @@ -330,17 +284,8 @@ public class SCXMLSemanticsImpl implemen if (tt instanceof State) { State ts = (State) tt; Initial ini = ts.getInitial(); - if (ts.isComposite() && ini != null) { - try { - for (Action initialAct : ini.getTransition(). - getActions()) { - initialAct.execute(evtDispatcher, - errRep, scInstance, appLog, internalEvents); - } - } catch (SCXMLExpressionException e) { - errRep.onError(ErrorConstants.EXPRESSION_ERROR, - e.getMessage(), ini); - } + if (ts.isComposite() && ini != null) { // TODO: use step.getDefaultEntrySet().contains(tt) instead + executeContent(ini.getTransition(), evtDispatcher, errRep, scInstance, internalEvents); } if (ts.isFinal()) { State parent = (State) ts.getParent(); @@ -368,7 +313,7 @@ public class SCXMLSemanticsImpl implemen } if (finCount == pCount) { te = new TriggerEvent(p.getId() + ".done", - TriggerEvent.CHANGE_EVENT); + TriggerEvent.CHANGE_EVENT); internalEvents.add(te); scInstance.setDone(p, true); } @@ -379,6 +324,69 @@ public class SCXMLSemanticsImpl implemen } /** + * @param step + * provides target states and entry list to fill in [out] + * @param stateMachine + * SCXML state machine [in] + * @param errRep + * ErrorReporter callback [inout] + * @param scInstance + * The state chart instance [in] + * @throws org.apache.commons.scxml2.model.ModelException + * in case there is a fatal SCXML object model problem. + */ + public void determineInitialStates(final Step step, final SCXML stateMachine, final ErrorReporter errRep, + final SCInstance scInstance) + throws ModelException { + TransitionTarget tmp = stateMachine.getInitialTarget(); + if (tmp == null) { + errRep.onError(ErrorConstants.NO_INITIAL, + "SCXML initialstate is missing!", stateMachine); + } else { + Set<TransitionTarget> targets = step.getAfterStatus().getStates(); + targets.add(tmp); + determineTargetStates(targets, errRep, scInstance); + //set of ALL entered states (even if initialState is a jump-over) + Set<TransitionTarget> onEntry = SCXMLHelper.getAncestorClosure(targets, null); + // sort onEntry according state hierarchy + TransitionTarget[] oen = onEntry.toArray(new TransitionTarget[onEntry.size()]); + onEntry.clear(); + Arrays.sort(oen, getTTComparator()); + // we need to impose reverse order for the onEntry list + List<TransitionTarget> entering = Arrays.asList(oen); + Collections.reverse(entering); + step.getEntryList().addAll(entering); + + } + } + + /** + * Executes all OnExit/Transition/OnEntry transitional actions. + * + * @param step + * provides EntryList, TransitList, ExitList gets + * updated its AfterStatus/Events + * @param stateMachine + * state machine - SCXML instance + * @param evtDispatcher + * the event dispatcher - EventDispatcher instance + * @param errRep + * error reporter + * @param scInstance + * The state chart instance + * @throws ModelException + * in case there is a fatal SCXML object model problem. + */ + public void executeActions(final Step step, final SCXML stateMachine, + final EventDispatcher evtDispatcher, + final ErrorReporter errRep, final SCInstance scInstance) + throws ModelException { + exitStates(step, stateMachine, evtDispatcher, errRep, scInstance); + executeTransitionContent(step, stateMachine, evtDispatcher, errRep, scInstance); + enterStates(step, stateMachine, evtDispatcher, errRep, scInstance); + } + + /** * @param stateMachine * a SM to traverse [in] * @param step @@ -447,15 +455,7 @@ public class SCXMLSemanticsImpl implemen if (finalizeMatch(s.getId(), allEvents)) { Finalize fn = s.getInvoke().getFinalize(); if (fn != null) { - try { - for (Action fnAct : fn.getActions()) { - fnAct.execute(evtDispatcher, errRep, scInstance, appLog, - step.getAfterStatus().getEvents()); - } - } catch (SCXMLExpressionException e) { - errRep.onError(ErrorConstants.EXPRESSION_ERROR, - e.getMessage(), fn); - } + executeContent(fn, evtDispatcher, errRep, scInstance, step.getAfterStatus().getEvents()); } } }