📄 scxmlsemanticsimpl.java
字号:
}
scInstance.setLastConfiguration(h, shallow);
}
}
shallow = null;
deep = null;
}
}
}
}
/**
* Follow the candidate transitions for this execution Step, and update the
* lists of entered and exited states accordingly.
*
* @param step The current Step
* @param errorReporter The ErrorReporter for the current environment
* @param scInstance The state chart instance
*
* @throws ModelException
* in case there is a fatal SCXML object model problem.
*/
public void followTransitions(final Step step,
final ErrorReporter errorReporter, final SCInstance scInstance)
throws ModelException {
Set currentStates = step.getBeforeStatus().getStates();
List transitions = step.getTransitList();
// DetermineExitedStates (currentStates, transitList) -> exitedStates
Set exitedStates = new HashSet();
for (Iterator i = transitions.iterator(); i.hasNext();) {
Transition t = (Transition) i.next();
Set ext = SCXMLHelper.getStatesExited(t, currentStates);
exitedStates.addAll(ext);
}
// compute residual states - these are preserved from the previous step
Set residual = new HashSet(currentStates);
residual.removeAll(exitedStates);
// SeedTargetSet (residual, transitList) -> seedSet
Set seedSet = seedTargetSet(residual, transitions, errorReporter);
// DetermineTargetStates (initialTargetSet) -> targetSet
Set targetSet = step.getAfterStatus().getStates();
targetSet.addAll(seedSet); //copy to preserve seedSet
determineTargetStates(targetSet, errorReporter, scInstance);
// BuildOnEntryList (targetSet, seedSet) -> entryList
Set entered = SCXMLHelper.getAncestorClosure(targetSet, seedSet);
seedSet.clear();
for (Iterator i = transitions.iterator(); i.hasNext();) {
Transition t = (Transition) i.next();
List paths = t.getPaths();
for (int j = 0; j < paths.size(); j++) {
Path p = (Path) paths.get(j);
entered.addAll(p.getDownwardSegment());
}
// If target is a History pseudo state, remove from entered list
List rtargets = t.getRuntimeTargets();
for (int j = 0; j < rtargets.size(); j++) {
TransitionTarget tt = (TransitionTarget) rtargets.get(j);
if (tt instanceof History) {
entered.remove(tt);
}
}
}
// Check whether the computed state config is legal
targetSet.addAll(residual);
residual.clear();
if (!SCXMLHelper.isLegalConfig(targetSet, errorReporter)) {
throw new ModelException("Illegal state machine configuration!");
}
// sort onEntry and onExit according state hierarchy
Object[] oex = exitedStates.toArray();
exitedStates.clear();
Object[] oen = entered.toArray();
entered.clear();
Arrays.sort(oex, getTTComparator());
Arrays.sort(oen, getTTComparator());
step.getExitList().addAll(Arrays.asList(oex));
// we need to impose reverse order for the onEntry list
List entering = Arrays.asList(oen);
Collections.reverse(entering);
step.getEntryList().addAll(entering);
// reset 'done' flag
for (Iterator reset = entering.iterator(); reset.hasNext();) {
Object o = reset.next();
if (o instanceof State) {
scInstance.setDone((State) o, false);
}
}
}
/**
* Process any existing invokes, includes forwarding external events,
* and executing any finalize handlers.
*
* @param events
* The events to be forwarded
* @param errRep
* ErrorReporter callback
* @param scInstance
* The state chart instance
* @throws ModelException
* in case there is a fatal SCXML object model problem.
*/
public void processInvokes(final TriggerEvent[] events,
final ErrorReporter errRep, final SCInstance scInstance)
throws ModelException {
Set allEvents = new HashSet();
allEvents.addAll(Arrays.asList(events));
for (Iterator invokeIter = scInstance.getInvokers().entrySet().
iterator(); invokeIter.hasNext();) {
Map.Entry iEntry = (Map.Entry) invokeIter.next();
String parentId = ((TransitionTarget) iEntry.getKey()).getId();
if (!finalizeMatch(parentId, allEvents)) { // prevent cycles
Invoker inv = (Invoker) iEntry.getValue();
try {
inv.parentEvents(events);
} catch (InvokerException ie) {
appLog.error(ie.getMessage(), ie);
throw new ModelException(ie.getMessage(), ie.getCause());
}
}
}
}
/**
* Initiate any new invokes.
*
* @param step
* The current Step
* @param errRep
* ErrorReporter callback
* @param scInstance
* The state chart instance
*/
public void initiateInvokes(final Step step, final ErrorReporter errRep,
final SCInstance scInstance) {
Evaluator eval = scInstance.getEvaluator();
Collection internalEvents = step.getAfterStatus().getEvents();
for (Iterator iter = step.getAfterStatus().getStates().iterator();
iter.hasNext();) {
State s = (State) iter.next();
Context ctx = scInstance.getContext(s);
Invoke i = s.getInvoke();
if (i != null && scInstance.getInvoker(s) == null) {
String src = i.getSrc();
if (src == null) {
String srcexpr = i.getSrcexpr();
Object srcObj = null;
try {
ctx.setLocal(NAMESPACES_KEY, i.getNamespaces());
srcObj = eval.eval(ctx, srcexpr);
ctx.setLocal(NAMESPACES_KEY, null);
src = String.valueOf(srcObj);
} catch (SCXMLExpressionException see) {
errRep.onError(ErrorConstants.EXPRESSION_ERROR,
see.getMessage(), i);
}
}
String source = src;
PathResolver pr = i.getPathResolver();
if (pr != null) {
source = i.getPathResolver().resolvePath(src);
}
String ttype = i.getTargettype();
Invoker inv = null;
try {
inv = scInstance.newInvoker(ttype);
} catch (InvokerException ie) {
TriggerEvent te = new TriggerEvent(s.getId()
+ ".invoke.failed", TriggerEvent.ERROR_EVENT);
internalEvents.add(te);
continue;
}
inv.setParentStateId(s.getId());
inv.setSCInstance(scInstance);
List params = i.params();
Map args = new HashMap();
for (Iterator pIter = params.iterator(); pIter.hasNext();) {
Param p = (Param) pIter.next();
String argExpr = p.getExpr();
Object argValue = null;
ctx.setLocal(NAMESPACES_KEY, p.getNamespaces());
// Do we have an "expr" attribute?
if (argExpr != null && argExpr.trim().length() > 0) {
// Yes, evaluate and store as parameter value
try {
argValue = eval.eval(ctx, argExpr);
} catch (SCXMLExpressionException see) {
errRep.onError(ErrorConstants.EXPRESSION_ERROR,
see.getMessage(), i);
}
} else {
// No. Does value of "name" attribute refer to a valid
// location in the data model?
try {
argValue = eval.evalLocation(ctx, p.getName());
if (argValue == null) {
// Generate error, 4.3.1 in WD-scxml-20080516
TriggerEvent te = new TriggerEvent(s.getId()
+ ERR_ILLEGAL_ALLOC,
TriggerEvent.ERROR_EVENT);
internalEvents.add(te);
}
} catch (SCXMLExpressionException see) {
errRep.onError(ErrorConstants.EXPRESSION_ERROR,
see.getMessage(), i);
}
}
ctx.setLocal(NAMESPACES_KEY, null);
args.put(p.getName(), argValue);
}
try {
inv.invoke(source, args);
} catch (InvokerException ie) {
TriggerEvent te = new TriggerEvent(s.getId()
+ ".invoke.failed", TriggerEvent.ERROR_EVENT);
internalEvents.add(te);
continue;
}
scInstance.setInvoker(s, inv);
}
}
}
/**
* Implements prefix match, that is, if, for example,
* "mouse.click" is a member of eventOccurrences and a
* transition is triggered by "mouse", the method returns true.
*
* @param transEvent
* a trigger event of a transition
* @param eventOccurrences
* current events
* @return true/false
*/
protected boolean eventMatch(final String transEvent,
final Set eventOccurrences) {
if (SCXMLHelper.isStringEmpty(transEvent)) { // Eventless transition
return true;
} else {
String trimTransEvent = transEvent.trim();
Iterator i = eventOccurrences.iterator();
while (i.hasNext()) {
TriggerEvent te = (TriggerEvent) i.next();
String event = te.getName();
if (event == null) {
continue; // Unnamed events
}
String trimEvent = event.trim();
if (trimEvent.equals(trimTransEvent)) {
return true; // Match
} else if (te.getType() != TriggerEvent.CHANGE_EVENT
&& trimTransEvent.equals("*")) {
return true; // Wildcard, skip gen'ed ones like .done etc.
} else if (trimTransEvent.endsWith(".*")
&& trimEvent.startsWith(trimTransEvent.substring(0,
trimTransEvent.length() - 1))) {
return true; // Prefixed wildcard
}
}
return false;
}
}
/**
* Implements event prefix match to ascertain <finalize> execution.
*
* @param parentStateId
* the ID of the parent state of the <invoke> holding
* the <finalize>
* @param eventOccurrences
* current events
* @return true/false
*/
protected boolean finalizeMatch(final String parentStateId,
final Set eventOccurrences) {
String prefix = parentStateId + ".invoke."; // invoke prefix
Iterator i = eventOccurrences.iterator();
while (i.hasNext()) {
String evt = ((TriggerEvent) i.next()).getName();
if (evt == null) {
continue; // Unnamed events
} else if (evt.trim().startsWith(prefix)) {
return true;
}
}
return false;
}
/**
* TransitionTargetComparator factory method.
* @return Comparator The TransitionTarget comparator
*/
protected Comparator getTTComparator() {
return targetComparator;
}
/**
* Set the log used by this <code>SCXMLSemantics</code> instance.
*
* @param log The new log.
*/
protected void setLog(final Log log) {
this.appLog = log;
}
/**
* Get the log used by this <code>SCXMLSemantics</code> instance.
*
* @return Log The log being used.
*/
protected Log getLog() {
return appLog;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -