📄 scxmlexecutor.java
字号:
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.scxml.model.Datamodel;
import org.apache.commons.scxml.model.History;
import org.apache.commons.scxml.model.ModelException;
import org.apache.commons.scxml.model.SCXML;
import org.apache.commons.scxml.model.State;
import org.apache.commons.scxml.model.Transition;
import org.apache.commons.scxml.model.TransitionTarget;
import org.apache.commons.scxml.semantics.SCXMLSemanticsImpl;
/**
* <p>The SCXML "engine" that executes SCXML documents. The
* particular semantics used by this engine for executing the SCXML are
* encapsulated in the SCXMLSemantics implementation that it uses.</p>
*
* <p>The default implementation is
* <code>org.apache.commons.scxml.semantics.SCXMLSemanticsImpl</code></p>
*
* @see SCXMLSemantics
*/
public class SCXMLExecutor implements Serializable {
/**
* Serial version UID.
*/
private static final long serialVersionUID = 1L;
/**
* The Logger for the SCXMLExecutor.
*/
private Log log = LogFactory.getLog(SCXMLExecutor.class);
/**
* The stateMachine being executed.
*/
private SCXML stateMachine;
/**
* The current status of the stateMachine.
*/
private Status currentStatus;
/**
* The event dispatcher to interface with external documents etc.
*/
private EventDispatcher eventdispatcher;
/**
* The environment specific error reporter.
*/
private ErrorReporter errorReporter = null;
/**
* Run-to-completion.
*/
private boolean superStep = true;
/**
* Interpretation semantics.
*/
private SCXMLSemantics semantics;
/**
* The SCInstance.
*/
private SCInstance scInstance;
/**
* The worker method.
* Re-evaluates current status whenever any events are triggered.
*
* @param evts
* an array of external events which triggered during the last
* time quantum
* @throws ModelException in case there is a fatal SCXML object
* model problem.
*/
public synchronized void triggerEvents(final TriggerEvent[] evts)
throws ModelException {
// Set event data, saving old values
Object[] oldData = setEventData(evts);
// Forward events (external only) to any existing invokes,
// and finalize processing
semantics.processInvokes(evts, errorReporter, scInstance);
List evs = new ArrayList(Arrays.asList(evts));
Step step = null;
do {
// CreateStep
step = new Step(evs, currentStatus);
// EnumerateReachableTransitions
semantics.enumerateReachableTransitions(stateMachine, step,
errorReporter);
// FilterTransitionSet
semantics.filterTransitionsSet(step, eventdispatcher,
errorReporter, scInstance);
// FollowTransitions
semantics.followTransitions(step, errorReporter, scInstance);
// UpdateHistoryStates
semantics.updateHistoryStates(step, errorReporter, scInstance);
// ExecuteActions
semantics.executeActions(step, stateMachine, eventdispatcher,
errorReporter, scInstance);
// AssignCurrentStatus
updateStatus(step);
// ***Cleanup external events if superStep
if (superStep) {
evs.clear();
}
} while (superStep && currentStatus.getEvents().size() > 0);
// InitiateInvokes only after state machine has stabilized
semantics.initiateInvokes(step, errorReporter, scInstance);
// Restore event data
restoreEventData(oldData);
logState();
}
/**
* Convenience method when only one event needs to be triggered.
*
* @param evt
* the external events which triggered during the last
* time quantum
* @throws ModelException in case there is a fatal SCXML object
* model problem.
*/
public void triggerEvent(final TriggerEvent evt)
throws ModelException {
triggerEvents(new TriggerEvent[] {evt});
}
/**
* Constructor.
*
* @param expEvaluator The expression evaluator
* @param evtDisp The event dispatcher
* @param errRep The error reporter
*/
public SCXMLExecutor(final Evaluator expEvaluator,
final EventDispatcher evtDisp, final ErrorReporter errRep) {
this(expEvaluator, evtDisp, errRep, null);
}
/**
* Convenience constructor.
*/
public SCXMLExecutor() {
this(null, null, null, null);
}
/**
* Constructor.
*
* @param expEvaluator The expression evaluator
* @param evtDisp The event dispatcher
* @param errRep The error reporter
* @param semantics The SCXML semantics
*/
public SCXMLExecutor(final Evaluator expEvaluator,
final EventDispatcher evtDisp, final ErrorReporter errRep,
final SCXMLSemantics semantics) {
this.eventdispatcher = evtDisp;
this.errorReporter = errRep;
this.currentStatus = new Status();
this.stateMachine = null;
if (semantics == null) {
// Use default semantics, if none provided
this.semantics = new SCXMLSemanticsImpl();
} else {
this.semantics = semantics;
}
this.scInstance = new SCInstance(this);
this.scInstance.setEvaluator(expEvaluator);
}
/**
* Clear all state and begin from "initialstate" indicated
* on root SCXML element.
*
* @throws ModelException in case there is a fatal SCXML object
* model problem.
*/
public synchronized void reset() throws ModelException {
// Reset all variable contexts
Context rootCtx = scInstance.getRootContext();
// Clone root datamodel
if (stateMachine == null) {
log.error(ERR_NO_STATE_MACHINE);
throw new ModelException(ERR_NO_STATE_MACHINE);
} else {
Datamodel rootdm = stateMachine.getDatamodel();
SCXMLHelper.cloneDatamodel(rootdm, rootCtx,
scInstance.getEvaluator(), log);
}
// all states and parallels, only states have variable contexts
for (Iterator i = stateMachine.getTargets().values().iterator();
i.hasNext();) {
TransitionTarget tt = (TransitionTarget) i.next();
if (tt instanceof State) {
Context context = scInstance.lookupContext(tt);
if (context != null) {
context.reset();
Datamodel dm = tt.getDatamodel();
if (dm != null) {
SCXMLHelper.cloneDatamodel(dm, context,
scInstance.getEvaluator(), log);
}
}
} else if (tt instanceof History) {
scInstance.reset((History) tt);
}
}
// CreateEmptyStatus
currentStatus = new Status();
Step step = new Step(null, currentStatus);
// DetermineInitialStates
semantics.determineInitialStates(stateMachine,
step.getAfterStatus().getStates(),
step.getEntryList(), errorReporter, scInstance);
// ExecuteActions
semantics.executeActions(step, stateMachine, eventdispatcher,
errorReporter, scInstance);
// AssignCurrentStatus
updateStatus(step);
// Execute Immediate Transitions
if (superStep && currentStatus.getEvents().size() > 0) {
this.triggerEvents(new TriggerEvent[0]);
} else {
// InitiateInvokes only after state machine has stabilized
semantics.initiateInvokes(step, errorReporter, scInstance);
logState();
}
}
/**
* Get the current status.
*
* @return The current Status
*/
public synchronized Status getCurrentStatus() {
return currentStatus;
}
/**
* Set the expression evaluator.
* <b>NOTE:</b> Should only be used before the executor is set in motion.
*
* @param evaluator The evaluator to set.
*/
public void setEvaluator(final Evaluator evaluator) {
this.scInstance.setEvaluator(evaluator);
}
/**
* Get the expression evaluator in use.
*
* @return Evaluator The evaluator in use.
*/
public Evaluator getEvaluator() {
return scInstance.getEvaluator();
}
/**
* Set the root context for this execution.
* <b>NOTE:</b> Should only be used before the executor is set in motion.
*
* @param rootContext The Context that ties to the host environment.
*/
public void setRootContext(final Context rootContext) {
this.scInstance.setRootContext(rootContext);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -