You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by at...@apache.org on 2017/12/10 03:04:21 UTC
[2/2] commons-scxml git commit: SCXML-259 Complete implementation and
handling of system variables _event and _ioprocessors
SCXML-259 Complete implementation and handling of system variables _event and _ioprocessors
Project: http://git-wip-us.apache.org/repos/asf/commons-scxml/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-scxml/commit/b4a10313
Tree: http://git-wip-us.apache.org/repos/asf/commons-scxml/tree/b4a10313
Diff: http://git-wip-us.apache.org/repos/asf/commons-scxml/diff/b4a10313
Branch: refs/heads/master
Commit: b4a10313c5c7017aa0afadca7ce6bce93278a1e2
Parents: a61c3c5
Author: Ate Douma <at...@apache.org>
Authored: Sun Dec 10 04:04:13 2017 +0100
Committer: Ate Douma <at...@apache.org>
Committed: Sun Dec 10 04:04:13 2017 +0100
----------------------------------------------------------------------
.../org/apache/commons/scxml2/EventBuilder.java | 90 ++++++++++++
.../apache/commons/scxml2/EventDispatcher.java | 12 ++
.../scxml2/ExternalSCXMLIOProcessor.java | 42 ++++++
.../commons/scxml2/ParentSCXMLIOProcessor.java | 47 ++++++
.../org/apache/commons/scxml2/SCInstance.java | 2 +-
.../commons/scxml2/SCXMLExecutionContext.java | 28 ++--
.../apache/commons/scxml2/SCXMLExecutor.java | 17 ++-
.../apache/commons/scxml2/SCXMLIOProcessor.java | 2 +-
.../org/apache/commons/scxml2/TriggerEvent.java | 119 ++++++++-------
.../scxml2/env/AbstractStateMachine.java | 4 +-
.../commons/scxml2/env/SimpleDispatcher.java | 99 +++++++------
.../scxml2/env/javascript/init_global.js | 4 +-
.../commons/scxml2/invoke/AsyncTrigger.java | 59 --------
.../scxml2/invoke/SimpleSCXMLInvoker.java | 35 ++---
.../org/apache/commons/scxml2/model/Action.java | 4 +-
.../scxml2/model/ActionExecutionError.java | 57 ++++++++
.../apache/commons/scxml2/model/Foreach.java | 4 +-
.../org/apache/commons/scxml2/model/If.java | 3 +-
.../org/apache/commons/scxml2/model/Invoke.java | 27 ++--
.../org/apache/commons/scxml2/model/Raise.java | 3 +-
.../org/apache/commons/scxml2/model/Send.java | 146 ++++++++++---------
.../commons/scxml2/model/TransitionalState.java | 2 +-
.../org/apache/commons/scxml2/model/Var.java | 3 +-
.../scxml2/semantics/SCXMLSemanticsImpl.java | 68 +++++----
.../commons/scxml2/system/EventVariable.java | 20 +++
.../commons/scxml2/test/StandaloneUtils.java | 7 +-
.../apache/commons/scxml2/EventDataTest.java | 20 +--
.../apache/commons/scxml2/SCXMLTestHelper.java | 16 +-
.../apache/commons/scxml2/TriggerEventTest.java | 26 ++--
.../scxml2/env/javascript/JSExampleTest.java | 4 +-
.../scxml2/invoke/InvokeParamNameTest.java | 4 +-
.../apache/commons/scxml2/model/CancelTest.java | 5 +-
.../commons/scxml2/model/DatamodelTest.java | 6 +-
.../org/apache/commons/scxml2/model/Hello.java | 4 +-
.../apache/commons/scxml2/model/SendTest.java | 4 +-
.../scxml2/model/StatelessModelTest.java | 3 +-
.../scxml2/model/actions-initial-test.xml | 2 +-
.../scxml2/model/actions-parallel-test.xml | 2 +-
.../commons/scxml2/model/actions-state-test.xml | 2 +-
.../org/apache/commons/scxml2/w3c/tests.xml | 26 ++--
40 files changed, 640 insertions(+), 388 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/b4a10313/src/main/java/org/apache/commons/scxml2/EventBuilder.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/EventBuilder.java b/src/main/java/org/apache/commons/scxml2/EventBuilder.java
new file mode 100644
index 0000000..d43ec49
--- /dev/null
+++ b/src/main/java/org/apache/commons/scxml2/EventBuilder.java
@@ -0,0 +1,90 @@
+/*
+ * 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.scxml2;
+
+public class EventBuilder {
+
+ private final String name;
+ private final int type;
+ private String sendId;
+ private String origin;
+ private String originType;
+ private String invokeId;
+ private Object data;
+
+ public EventBuilder(final String name, final int type) {
+ this.name = name;
+ this.type = type;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public int getType() {
+ return type;
+ }
+
+ public String getSendId() {
+ return sendId;
+ }
+
+ public EventBuilder sendId(final String sendId) {
+ this.sendId = sendId;
+ return this;
+ }
+
+ public String getOrigin() {
+ return origin;
+ }
+
+ public EventBuilder origin(final String origin) {
+ this.origin = origin;
+ return this;
+ }
+
+ public String getOriginType() {
+ return originType;
+ }
+
+ public EventBuilder originType(final String originType) {
+ this.originType = originType;
+ return this;
+ }
+
+ public String getInvokeId() {
+ return invokeId;
+ }
+
+ public EventBuilder invokeId(final String invokeId) {
+ this.invokeId = invokeId;
+ return this;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public EventBuilder data(final Object data) {
+ this.data = data;
+ return this;
+ }
+
+ public TriggerEvent build() {
+ return new TriggerEvent(name, type, sendId, origin, originType, invokeId, data);
+ }
+}
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/b4a10313/src/main/java/org/apache/commons/scxml2/EventDispatcher.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/EventDispatcher.java b/src/main/java/org/apache/commons/scxml2/EventDispatcher.java
index 6f0a8f1..b57b81f 100644
--- a/src/main/java/org/apache/commons/scxml2/EventDispatcher.java
+++ b/src/main/java/org/apache/commons/scxml2/EventDispatcher.java
@@ -18,6 +18,8 @@ package org.apache.commons.scxml2;
import java.util.Map;
+import org.apache.commons.scxml2.invoke.Invoker;
+
/**
* The event controller interface used to send messages containing
* events or other information directly to another SCXML Interpreter,
@@ -28,6 +30,16 @@ import java.util.Map;
public interface EventDispatcher {
/**
+ * A EventDispatcher keeps track of outstanding (pending) events to be send on behalf of the statemachine
+ * it is 'attached' to.
+ * To support easy setup and configuration of an invoked child statemachine (see {@link Invoker})
+ * the EventDispatcher provides this newInstnace method to allow creating a new instance without sharing its
+ * internal state..
+ * @return a new EventDispatcher instance for usage in an invoked child statemachine.
+ */
+ EventDispatcher newInstance();
+
+ /**
* Cancel the specified send message.
*
* @param sendId The ID of the send message to cancel
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/b4a10313/src/main/java/org/apache/commons/scxml2/ExternalSCXMLIOProcessor.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/ExternalSCXMLIOProcessor.java b/src/main/java/org/apache/commons/scxml2/ExternalSCXMLIOProcessor.java
new file mode 100644
index 0000000..be14a3d
--- /dev/null
+++ b/src/main/java/org/apache/commons/scxml2/ExternalSCXMLIOProcessor.java
@@ -0,0 +1,42 @@
+/*
+ * 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.scxml2;
+
+/**
+ * The ExternalSCXMLIOProcessor is registered in the _ioprocessors system variable under the
+ * {@link #DEFAULT_EVENT_PROCESSOR} key <b>and</b> maintains a {@link #getLocation() location} field
+ * <pre>
+ * <em>whose value holds an address that external entities can use to communicate with this SCXML session using the SCXML Event I/O Processor.</em></pre>
+ * @see <a href="https://www.w3.org/TR/scxml/#SCXMLEventProcessor">SCXML specification C.1.1 _ioprocessors Value</a>
+ */
+public class ExternalSCXMLIOProcessor implements SCXMLIOProcessor {
+
+ private SCXMLIOProcessor processor;
+
+ public ExternalSCXMLIOProcessor(final SCXMLIOProcessor processor) {
+ this.processor = processor;
+ }
+
+ @Override
+ public void addEvent(final TriggerEvent event) {
+ processor.addEvent(event);
+ }
+
+ public String getLocation() {
+ return SCXML_EVENT_PROCESSOR;
+ }
+}
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/b4a10313/src/main/java/org/apache/commons/scxml2/ParentSCXMLIOProcessor.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/ParentSCXMLIOProcessor.java b/src/main/java/org/apache/commons/scxml2/ParentSCXMLIOProcessor.java
new file mode 100644
index 0000000..f3cc08c
--- /dev/null
+++ b/src/main/java/org/apache/commons/scxml2/ParentSCXMLIOProcessor.java
@@ -0,0 +1,47 @@
+/*
+ * 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.scxml2;
+
+public class ParentSCXMLIOProcessor implements SCXMLIOProcessor {
+
+ private SCXMLIOProcessor processor;
+ private final String invokeId;
+
+ public ParentSCXMLIOProcessor(final SCXMLIOProcessor processor, final String invokeId) {
+ this.processor = processor;
+ this.invokeId = invokeId;
+ }
+
+ @Override
+ public synchronized void addEvent(final TriggerEvent event) {
+ if (processor != null) {
+ processor.addEvent(event);
+ }
+ }
+
+ public String getInvokeId() {
+ return invokeId;
+ }
+
+ public synchronized void close() {
+ processor = null;
+ }
+
+ public synchronized boolean isClosed() {
+ return processor == null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/b4a10313/src/main/java/org/apache/commons/scxml2/SCInstance.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/SCInstance.java b/src/main/java/org/apache/commons/scxml2/SCInstance.java
index 299df9c..5fe715f 100644
--- a/src/main/java/org/apache/commons/scxml2/SCInstance.java
+++ b/src/main/java/org/apache/commons/scxml2/SCInstance.java
@@ -348,7 +348,7 @@ public class SCInstance implements Serializable {
setValue = true;
} catch (SCXMLExpressionException see) {
if (internalIOProcessor != null) {
- internalIOProcessor.addEvent(new TriggerEvent(TriggerEvent.ERROR_EXECUTION, TriggerEvent.ERROR_EVENT));
+ internalIOProcessor.addEvent(new EventBuilder(TriggerEvent.ERROR_EXECUTION, TriggerEvent.ERROR_EVENT).build());
}
errorReporter.onError(ErrorConstants.EXPRESSION_ERROR, see.getMessage(), datum);
} finally {
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/b4a10313/src/main/java/org/apache/commons/scxml2/SCXMLExecutionContext.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/SCXMLExecutionContext.java b/src/main/java/org/apache/commons/scxml2/SCXMLExecutionContext.java
index 545feac..ec4dcea 100644
--- a/src/main/java/org/apache/commons/scxml2/SCXMLExecutionContext.java
+++ b/src/main/java/org/apache/commons/scxml2/SCXMLExecutionContext.java
@@ -149,11 +149,11 @@ public class SCXMLExecutionContext implements SCXMLIOProcessor {
this.scInstance = new SCInstance(this, this.evaluator, this.errorReporter);
this.actionExecutionContext = new ActionExecutionContext(this);
- ioProcessors.put(SCXMLIOProcessor.DEFAULT_EVENT_PROCESSOR, getExternalIOProcessor());
- ioProcessors.put(SCXMLIOProcessor.SCXML_EVENT_PROCESSOR, getExternalIOProcessor());
+ ioProcessors.put(SCXMLIOProcessor.SCXML_EVENT_PROCESSOR, new ExternalSCXMLIOProcessor(getExternalIOProcessor()));
+ ioProcessors.put(SCXMLIOProcessor.DEFAULT_EVENT_PROCESSOR, ioProcessors.get(SCXMLIOProcessor.SCXML_EVENT_PROCESSOR));
ioProcessors.put(SCXMLIOProcessor.INTERNAL_EVENT_PROCESSOR, getInternalIOProcessor());
- if (scxmlExecutor.getParentSCXMLExecutor() != null) {
- ioProcessors.put(SCXMLIOProcessor.PARENT_EVENT_PROCESSOR, scxmlExecutor.getParentSCXMLExecutor());
+ if (scxmlExecutor.getParentSCXMLIOProcessor() != null) {
+ ioProcessors.put(SCXMLIOProcessor.PARENT_EVENT_PROCESSOR, scxmlExecutor.getParentSCXMLIOProcessor());
}
initializeIOProcessors();
registerInvokerClass(SCXML_INVOKER_TYPE_URI, SimpleSCXMLInvoker.class);
@@ -414,13 +414,23 @@ public class SCXMLExecutionContext implements SCXMLIOProcessor {
}
/**
+ * Trivial utility method needed for SCXML IRP test 216 which (IMO incorrectly uses http://www.w3.org/TR/scxml
+ * (no trailing /) while the SCXML spec explicitly states http://www.w3.org/TR/scxml/ should be used (supported)
+ * @param uri
+ * @return
+ */
+ private final String stripTrailingSlash(final String uri) {
+ return uri.endsWith("/") ? uri.substring(0, uri.length()-1) : uri;
+ }
+
+ /**
* Register an Invoker for this target type.
*
* @param type The target type (specified by "type" attribute of the invoke element).
* @param invokerClass The Invoker class.
*/
protected void registerInvokerClass(final String type, final Class<? extends Invoker> invokerClass) {
- invokerClasses.put(type, invokerClass);
+ invokerClasses.put(stripTrailingSlash(type), invokerClass);
}
/**
@@ -429,7 +439,7 @@ public class SCXMLExecutionContext implements SCXMLIOProcessor {
* @param type The target type (specified by "type" attribute of the invoke element).
*/
protected void unregisterInvokerClass(final String type) {
- invokerClasses.remove(type);
+ invokerClasses.remove(stripTrailingSlash(type));
}
/**
@@ -442,9 +452,9 @@ public class SCXMLExecutionContext implements SCXMLIOProcessor {
* @throws InvokerException When a suitable {@link Invoker} cannot be instantiated.
*/
public Invoker newInvoker(final String type) throws InvokerException {
- Class<? extends Invoker> invokerClass = invokerClasses.get(type);
+ Class<? extends Invoker> invokerClass = invokerClasses.get(stripTrailingSlash(type));
if (invokerClass == null) {
- throw new InvokerException("No Invoker registered for type \"" + type + "\"");
+ throw new InvokerException("No Invoker registered for type \"" + stripTrailingSlash(type) + "\"");
}
try {
return invokerClass.newInstance();
@@ -515,7 +525,7 @@ public class SCXMLExecutionContext implements SCXMLIOProcessor {
try {
invokers.get(invokeId).cancel();
} catch (InvokerException ie) {
- TriggerEvent te = new TriggerEvent("failed.invoke.cancel."+invokeId, TriggerEvent.ERROR_EVENT);
+ TriggerEvent te = new EventBuilder("failed.invoke.cancel."+invokeId, TriggerEvent.ERROR_EVENT).build();
addEvent(te);
}
removeInvoker(invoke);
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/b4a10313/src/main/java/org/apache/commons/scxml2/SCXMLExecutor.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/SCXMLExecutor.java b/src/main/java/org/apache/commons/scxml2/SCXMLExecutor.java
index d22fe1d..a2b6bfd 100644
--- a/src/main/java/org/apache/commons/scxml2/SCXMLExecutor.java
+++ b/src/main/java/org/apache/commons/scxml2/SCXMLExecutor.java
@@ -54,9 +54,9 @@ public class SCXMLExecutor implements SCXMLIOProcessor {
private Log log = LogFactory.getLog(SCXMLExecutor.class);
/**
- * Parent SCXMLExecutor
+ * Parent SCXMLIOProcessor
*/
- private SCXMLExecutor parentSCXMLExecutor;
+ private ParentSCXMLIOProcessor parentSCXMLIOProcessor;
/**
* Interpretation semantics.
@@ -112,20 +112,21 @@ public class SCXMLExecutor implements SCXMLIOProcessor {
*
* @param parentSCXMLExecutor the parent SCXMLExecutor
*/
- public SCXMLExecutor(final SCXMLExecutor parentSCXMLExecutor) throws ModelException {
- this.parentSCXMLExecutor = parentSCXMLExecutor;
+ public SCXMLExecutor(final SCXMLExecutor parentSCXMLExecutor, final String invokeId, final SCXML scxml) throws ModelException {
+ this.parentSCXMLIOProcessor = new ParentSCXMLIOProcessor(parentSCXMLExecutor, invokeId);
this.semantics = parentSCXMLExecutor.semantics;
this.exctx = new SCXMLExecutionContext(this, parentSCXMLExecutor.getEvaluator(),
- parentSCXMLExecutor.getEventdispatcher(), parentSCXMLExecutor.getErrorReporter());
+ parentSCXMLExecutor.getEventdispatcher().newInstance(), parentSCXMLExecutor.getErrorReporter());
getSCInstance().setSingleContext(parentSCXMLExecutor.isSingleContext());
getSCInstance().setStrict(parentSCXMLExecutor.isStrict());
+ getSCInstance().setStateMachine(scxml);
}
/**
- * @return the parent SCXMLExecutor (if any)
+ * @return the parent SCXMLIOProcessor (if any)
*/
- protected SCXMLExecutor getParentSCXMLExecutor() {
- return parentSCXMLExecutor;
+ public ParentSCXMLIOProcessor getParentSCXMLIOProcessor() {
+ return parentSCXMLIOProcessor;
}
/**
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/b4a10313/src/main/java/org/apache/commons/scxml2/SCXMLIOProcessor.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/SCXMLIOProcessor.java b/src/main/java/org/apache/commons/scxml2/SCXMLIOProcessor.java
index bafb86a..289b6d3 100644
--- a/src/main/java/org/apache/commons/scxml2/SCXMLIOProcessor.java
+++ b/src/main/java/org/apache/commons/scxml2/SCXMLIOProcessor.java
@@ -33,7 +33,7 @@ public interface SCXMLIOProcessor {
String EVENT_PROCESSOR_ALIAS_PREFIX = "#_";
/**
- * Default SCXML I/O Event Processor alias
+ * Default external SCXML I/O Event Processor alias
*/
String SCXML_EVENT_PROCESSOR = "scxml";
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/b4a10313/src/main/java/org/apache/commons/scxml2/TriggerEvent.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/TriggerEvent.java b/src/main/java/org/apache/commons/scxml2/TriggerEvent.java
index fbf3328..438b8ab 100644
--- a/src/main/java/org/apache/commons/scxml2/TriggerEvent.java
+++ b/src/main/java/org/apache/commons/scxml2/TriggerEvent.java
@@ -23,7 +23,7 @@ import java.io.Serializable;
* defined in reference to SCXML.
*
* <b>NOTE:</b> Instances are {@link Serializable} as long as the associated
- * payload, if any, is {@link Serializable}.
+ * data, if any, is {@link Serializable}.
*
*/
public class TriggerEvent implements Serializable {
@@ -36,24 +36,21 @@ public class TriggerEvent implements Serializable {
*
* @param name The event name
* @param type The event type
- * @param payload The event payload, must be {@link Serializable}
+ * @deprecated use {@link EventBuilder instead}
*/
- public TriggerEvent(final String name, final int type,
- final Object payload) {
- super();
- this.name = name != null ? name.trim() : "";
- this.type = type;
- this.payload = payload;
+ public TriggerEvent(final String name, final int type) {
+ this(name, type, null, null, null, null, null);
}
- /**
- * Constructor.
- *
- * @param name The event name
- * @param type The event type
- */
- public TriggerEvent(final String name, final int type) {
- this(name, type, null);
+ TriggerEvent(final String name, final int type, final String sendId, final String origin,
+ final String originType, final String invokeId, final Object data) {
+ this.name = name != null ? name.trim() : "";
+ this.type = type;
+ this.sendId = sendId;
+ this.origin = origin;
+ this.originType = originType;
+ this.invokeId = invokeId;
+ this.data = data;
}
/**
@@ -122,45 +119,46 @@ public class TriggerEvent implements Serializable {
*/
public static final String ERROR_PLATFORM = "error.platform";
- /**
- * The event name.
- *
- */
- private String name;
-
- /**
- * The event type.
- *
- */
- private int type;
-
- /**
- * The event payload.
- *
- */
- private Object payload;
+ private final String name;
+ private final int type;
+ private final String sendId;
+ private final String origin;
+ private final String originType;
+ private final String invokeId;
+ private final Object data;
- /**
- * @return Returns the name.
- */
public String getName() {
return name;
}
- /**
- * @return Returns the payload.
- */
- public Object getPayload() {
- return payload;
- }
-
- /**
- * @return Returns the type.
- */
public int getType() {
return type;
}
+ public String getSendId() {
+ return sendId;
+ }
+
+ public String getOrigin() {
+ return origin;
+ }
+
+ public String getOriginType() {
+ return originType;
+ }
+
+ public String getInvokeId() {
+ return invokeId;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ private static boolean equals(final Object a, final Object b) {
+ return (a == null && b == null) || (a != null && a.equals(b));
+ }
+
/**
* Define an equals operator for TriggerEvent.
*
@@ -170,9 +168,12 @@ public class TriggerEvent implements Serializable {
public boolean equals(final Object obj) {
if (obj instanceof TriggerEvent) {
TriggerEvent te2 = (TriggerEvent) obj;
- if (type == te2.type && name.equals(te2.name)
- && ((payload == null && te2.payload == null)
- || (payload != null && payload.equals(te2.payload)))) {
+ if (type == te2.type && name.equals(te2.name) &&
+ equals(sendId, te2.sendId) &&
+ equals(origin, te2.origin) &&
+ equals(originType, te2.originType) &&
+ equals(invokeId, te2.invokeId) &&
+ equals(data, te2.data)) {
return true;
}
}
@@ -186,10 +187,22 @@ public class TriggerEvent implements Serializable {
*/
@Override
public String toString() {
- StringBuffer buf = new StringBuffer("TriggerEvent{name=");
- buf.append(name).append(",type=").append(type);
- if (payload != null) {
- buf.append(",payload=").append(payload.toString());
+ StringBuilder buf = new StringBuilder("TriggerEvent{name=");
+ buf.append(name).append(", type=").append(type);
+ if (sendId != null) {
+ buf.append(", sendid=").append(invokeId);
+ }
+ if (origin != null) {
+ buf.append(", origin=").append(invokeId);
+ }
+ if (originType != null) {
+ buf.append(", origintype=").append(invokeId);
+ }
+ if (invokeId != null) {
+ buf.append(", invokeid=").append(invokeId);
+ }
+ if (data != null) {
+ buf.append(", data=").append(data.toString());
}
buf.append("}");
return String.valueOf(buf);
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/b4a10313/src/main/java/org/apache/commons/scxml2/env/AbstractStateMachine.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/env/AbstractStateMachine.java b/src/main/java/org/apache/commons/scxml2/env/AbstractStateMachine.java
index 80b5d59..d72ec77 100644
--- a/src/main/java/org/apache/commons/scxml2/env/AbstractStateMachine.java
+++ b/src/main/java/org/apache/commons/scxml2/env/AbstractStateMachine.java
@@ -27,6 +27,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.scxml2.Context;
import org.apache.commons.scxml2.Evaluator;
+import org.apache.commons.scxml2.EventBuilder;
import org.apache.commons.scxml2.SCXMLExecutor;
import org.apache.commons.scxml2.SCXMLListener;
import org.apache.commons.scxml2.TriggerEvent;
@@ -197,8 +198,7 @@ public abstract class AbstractStateMachine {
* configuration.
*/
public boolean fireEvent(final String event) {
- TriggerEvent[] evts = {new TriggerEvent(event,
- TriggerEvent.SIGNAL_EVENT)};
+ TriggerEvent[] evts = {new EventBuilder(event, TriggerEvent.SIGNAL_EVENT).build()};
try {
engine.triggerEvents(evts);
} catch (ModelException me) {
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/b4a10313/src/main/java/org/apache/commons/scxml2/env/SimpleDispatcher.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/env/SimpleDispatcher.java b/src/main/java/org/apache/commons/scxml2/env/SimpleDispatcher.java
index c3332c9..60ae51f 100644
--- a/src/main/java/org/apache/commons/scxml2/env/SimpleDispatcher.java
+++ b/src/main/java/org/apache/commons/scxml2/env/SimpleDispatcher.java
@@ -25,9 +25,12 @@ import java.util.TimerTask;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.commons.scxml2.EventBuilder;
import org.apache.commons.scxml2.EventDispatcher;
+import org.apache.commons.scxml2.ParentSCXMLIOProcessor;
import org.apache.commons.scxml2.SCXMLIOProcessor;
import org.apache.commons.scxml2.TriggerEvent;
+import org.apache.commons.scxml2.model.ActionExecutionError;
/**
* <p>EventDispatcher implementation that can schedule <code>delay</code>ed
@@ -58,14 +61,9 @@ public class SimpleDispatcher implements EventDispatcher, Serializable {
private String id;
/**
- * The event name.
+ * The event
*/
- private String event;
-
- /**
- * The event payload, if any.
- */
- private Object payload;
+ private TriggerEvent event;
/**
* The target io processor
@@ -76,15 +74,13 @@ public class SimpleDispatcher implements EventDispatcher, Serializable {
* Constructor for events with payload.
*
* @param id The ID of the send element.
- * @param event The name of the event to be triggered.
- * @param payload The event payload, if any.
+ * @param event The event to be triggered.
* @param target The target io processor
*/
- DelayedEventTask(final String id, final String event, final Object payload, SCXMLIOProcessor target) {
+ DelayedEventTask(final String id, final TriggerEvent event, SCXMLIOProcessor target) {
super();
this.id = id;
this.event = event;
- this.payload = payload;
this.target = target;
}
@@ -94,9 +90,9 @@ public class SimpleDispatcher implements EventDispatcher, Serializable {
@Override
public void run() {
timers.remove(id);
- target.addEvent(new TriggerEvent(event, TriggerEvent.SIGNAL_EVENT, payload));
+ target.addEvent(event);
if (log.isDebugEnabled()) {
- log.debug("Fired event '" + event + "' as scheduled by "
+ log.debug("Fired event '" + event.getName() + "' as scheduled by "
+ "<send> with id '" + id + "'");
}
}
@@ -138,6 +134,12 @@ public class SimpleDispatcher implements EventDispatcher, Serializable {
return timers;
}
+
+ @Override
+ public SimpleDispatcher newInstance() {
+ return new SimpleDispatcher();
+ }
+
/**
* @see EventDispatcher#cancel(String)
*/
@@ -181,13 +183,15 @@ public class SimpleDispatcher implements EventDispatcher, Serializable {
if (type == null || type.equalsIgnoreCase(SCXMLIOProcessor.SCXML_EVENT_PROCESSOR) ||
type.equals(SCXMLIOProcessor.DEFAULT_EVENT_PROCESSOR)) {
-
+ String originType = SCXMLIOProcessor.DEFAULT_EVENT_PROCESSOR;
SCXMLIOProcessor ioProcessor;
boolean internal = false;
+ String origin = target;
if (target == null) {
ioProcessor = ioProcessors.get(SCXMLIOProcessor.SCXML_EVENT_PROCESSOR);
+ origin = SCXMLIOProcessor.SCXML_EVENT_PROCESSOR;
}
else if (ioProcessors.containsKey(target)) {
ioProcessor = ioProcessors.get(target);
@@ -198,44 +202,53 @@ public class SimpleDispatcher implements EventDispatcher, Serializable {
internal = true;
}
else {
- // We know of no other target
- if (log.isWarnEnabled()) {
- log.warn("<send>: Unavailable target - " + target);
+ if (target.startsWith(SCXMLIOProcessor.EVENT_PROCESSOR_ALIAS_PREFIX)) {
+ ioProcessors.get(SCXMLIOProcessor.INTERNAL_EVENT_PROCESSOR).addEvent(
+ new EventBuilder(TriggerEvent.ERROR_COMMUNICATION, TriggerEvent.ERROR_EVENT)
+ .sendId(id).build());
+ throw new ActionExecutionError(true, "<send>: Unavailable target - " + target);
+ } else {
+ ioProcessors.get(SCXMLIOProcessor.INTERNAL_EVENT_PROCESSOR).addEvent(
+ new EventBuilder(TriggerEvent.ERROR_EXECUTION, TriggerEvent.ERROR_EVENT)
+ .sendId(id).build());
+ throw new ActionExecutionError(true, "<send>: Invalid or unsupported target - " + target);
}
- ioProcessors.get(SCXMLIOProcessor.INTERNAL_EVENT_PROCESSOR).
- addEvent(new TriggerEvent(TriggerEvent.ERROR_EXECUTION, TriggerEvent.ERROR_EVENT));
- return; // done
}
if (event == null) {
- if (log.isWarnEnabled()) {
- log.warn("<send>: Cannot send without event name");
- }
- ioProcessors.get(SCXMLIOProcessor.INTERNAL_EVENT_PROCESSOR).
- addEvent(new TriggerEvent(TriggerEvent.ERROR_EXECUTION, TriggerEvent.ERROR_EVENT));
- }
-
- else if (!internal && delay > 0L) {
- // Need to schedule this one
- Timer timer = new Timer(true);
- timer.schedule(new DelayedEventTask(id, event, data, ioProcessor), delay);
- timers.put(id, timer);
- if (log.isDebugEnabled()) {
- log.debug("Scheduled event '" + event + "' with delay "
- + delay + "ms, as specified by <send> with id '"
- + id + "'");
- }
+ ioProcessors.get(SCXMLIOProcessor.INTERNAL_EVENT_PROCESSOR)
+ .addEvent(new EventBuilder(TriggerEvent.ERROR_EXECUTION, TriggerEvent.ERROR_EVENT).sendId(id).build());
+ throw new ActionExecutionError(true, "<send>: Cannot send without event name");
}
else {
- ioProcessor.addEvent(new TriggerEvent(event, TriggerEvent.SIGNAL_EVENT, data));
+ EventBuilder eventBuilder = new EventBuilder(event, TriggerEvent.SIGNAL_EVENT)
+ .sendId(id)
+ .data(data);
+ if (!internal) {
+ eventBuilder.origin(origin).originType(originType);
+ if (SCXMLIOProcessor.PARENT_EVENT_PROCESSOR.equals(target)) {
+ eventBuilder.invokeId(((ParentSCXMLIOProcessor)ioProcessor).getInvokeId());
+ }
+ if (delay > 0L) {
+ // Need to schedule this one
+ Timer timer = new Timer(true);
+ timer.schedule(new DelayedEventTask(id, eventBuilder.build(), ioProcessor), delay);
+ timers.put(id, timer);
+ if (log.isDebugEnabled()) {
+ log.debug("Scheduled event '" + event + "' with delay "
+ + delay + "ms, as specified by <send> with id '"
+ + id + "'");
+ }
+ return;
+ }
+ }
+ ioProcessor.addEvent(eventBuilder.build());
}
}
else {
- if (log.isWarnEnabled()) {
- log.warn("<send>: Unsupported type - " + type);
- }
- ioProcessors.get(SCXMLIOProcessor.INTERNAL_EVENT_PROCESSOR).
- addEvent(new TriggerEvent(TriggerEvent.ERROR_EXECUTION, TriggerEvent.ERROR_EVENT));
+ ioProcessors.get(SCXMLIOProcessor.INTERNAL_EVENT_PROCESSOR)
+ .addEvent(new EventBuilder(TriggerEvent.ERROR_EXECUTION, TriggerEvent.ERROR_EVENT).sendId(id).build());
+ throw new ActionExecutionError(true, "<send>: Unsupported type - " + type);
}
}
}
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/b4a10313/src/main/java/org/apache/commons/scxml2/env/javascript/init_global.js
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/env/javascript/init_global.js b/src/main/java/org/apache/commons/scxml2/env/javascript/init_global.js
index b4cb4fc..fccb6cb 100644
--- a/src/main/java/org/apache/commons/scxml2/env/javascript/init_global.js
+++ b/src/main/java/org/apache/commons/scxml2/env/javascript/init_global.js
@@ -79,13 +79,13 @@ Object.defineProperties(this, {
_scxmlProtected("_event.sendid")
},
get orgin() {
- return _scxmlSystemContext._event.orgin||undefined
+ return _scxmlSystemContext._event.origin||undefined
},
set origin(val) {
_scxmlProtected("_event.origin")
},
get origintype() {
- return _scxmlSystemContext._event.orgintype||undefined
+ return _scxmlSystemContext._event.origintype||undefined
},
set origintype(val) {
_scxmlProtected("_event.origintype")
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/b4a10313/src/main/java/org/apache/commons/scxml2/invoke/AsyncTrigger.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/invoke/AsyncTrigger.java b/src/main/java/org/apache/commons/scxml2/invoke/AsyncTrigger.java
deleted file mode 100644
index afa9dd8..0000000
--- a/src/main/java/org/apache/commons/scxml2/invoke/AsyncTrigger.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.scxml2.invoke;
-
-import org.apache.commons.scxml2.SCXMLIOProcessor;
-import org.apache.commons.scxml2.TriggerEvent;
-
-/**
- * Trigger the given {@link TriggerEvent} on the given
- * state machine executor asynchronously, once.
- */
-class AsyncTrigger implements Runnable {
-
- /** The SCXML state machine I/O Processor to deliver the event to. */
- private final SCXMLIOProcessor ioProcessor;
- /** The event to be triggered. */
- private final TriggerEvent event;
-
- /**
- * Constructor.
- *
- * @param ioProcessor The {@link org.apache.commons.scxml2.SCXMLIOProcessor} to trigger the event on.
- * @param event The {@link TriggerEvent}.
- */
- AsyncTrigger(final SCXMLIOProcessor ioProcessor, final TriggerEvent event) {
- this.ioProcessor = ioProcessor;
- this.event = event;
- }
-
- /**
- * Fire the trigger asynchronously.
- */
- public void start() {
- new Thread(this).start();
- }
-
- /**
- * Fire the event(s).
- */
- public void run() {
- ioProcessor.addEvent(event);
- }
-
-}
-
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/b4a10313/src/main/java/org/apache/commons/scxml2/invoke/SimpleSCXMLInvoker.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/invoke/SimpleSCXMLInvoker.java b/src/main/java/org/apache/commons/scxml2/invoke/SimpleSCXMLInvoker.java
index 44084a3..ee7262f 100644
--- a/src/main/java/org/apache/commons/scxml2/invoke/SimpleSCXMLInvoker.java
+++ b/src/main/java/org/apache/commons/scxml2/invoke/SimpleSCXMLInvoker.java
@@ -24,6 +24,7 @@ import java.util.Map;
import javax.xml.stream.XMLStreamException;
import org.apache.commons.scxml2.Context;
+import org.apache.commons.scxml2.EventBuilder;
import org.apache.commons.scxml2.SCXMLExecutor;
import org.apache.commons.scxml2.SCXMLIOProcessor;
import org.apache.commons.scxml2.TriggerEvent;
@@ -40,8 +41,8 @@ public class SimpleSCXMLInvoker implements Invoker, Serializable {
/** Serial version UID. */
private static final long serialVersionUID = 1L;
- /** Parent state ID. */
- private String parentStateId;
+ /** invokeId ID. */
+ private String invokeId;
/** Invoking parent SCXMLExecutor */
private SCXMLExecutor parentSCXMLExecutor;
/** The invoked state machine executor. */
@@ -55,7 +56,7 @@ public class SimpleSCXMLInvoker implements Invoker, Serializable {
*/
@Override
public String getInvokeId() {
- return parentStateId;
+ return invokeId;
}
/**
@@ -63,7 +64,7 @@ public class SimpleSCXMLInvoker implements Invoker, Serializable {
*/
@Override
public void setInvokeId(final String invokeId) {
- this.parentStateId = invokeId;
+ this.invokeId = invokeId;
this.cancelled = false;
}
@@ -101,26 +102,17 @@ public class SimpleSCXMLInvoker implements Invoker, Serializable {
throw new InvokerException(xse.getMessage(), xse.getCause());
}
try {
- executor = new SCXMLExecutor(parentSCXMLExecutor);
- executor.setStateMachine(scxml);
+ executor = new SCXMLExecutor(parentSCXMLExecutor, invokeId, scxml);
}
catch (ModelException me) {
throw new InvokerException(me);
}
- Context rootCtx = executor.getRootContext();
- for (Map.Entry<String, Object> entry : params.entrySet()) {
- rootCtx.setLocal(entry.getKey(), entry.getValue());
- }
executor.addListener(scxml, new SimpleSCXMLListener());
try {
- executor.go();
+ executor.run(params);
} catch (ModelException me) {
throw new InvokerException(me.getMessage(), me.getCause());
}
- if (executor.getStatus().isFinal()) {
- TriggerEvent te = new TriggerEvent("done.invoke."+parentStateId, TriggerEvent.SIGNAL_EVENT);
- new AsyncTrigger(parentSCXMLExecutor, te).start();
- }
}
/**
@@ -129,14 +121,8 @@ public class SimpleSCXMLInvoker implements Invoker, Serializable {
@Override
public void parentEvent(final TriggerEvent evt)
throws InvokerException {
- if (cancelled) {
- return; // no further processing should take place
- }
- boolean doneBefore = executor.getStatus().isFinal();
- executor.addEvent(evt);
- if (!doneBefore && executor.getStatus().isFinal()) {
- TriggerEvent te = new TriggerEvent("done.invoke."+parentStateId,TriggerEvent.SIGNAL_EVENT);
- new AsyncTrigger(parentSCXMLExecutor, te).start();
+ if (!cancelled) {
+ executor.addEvent(evt);
}
}
@@ -147,7 +133,8 @@ public class SimpleSCXMLInvoker implements Invoker, Serializable {
public void cancel()
throws InvokerException {
cancelled = true;
- executor.addEvent(new TriggerEvent("cancel.invoke."+parentStateId, TriggerEvent.CANCEL_EVENT));
+ executor.getParentSCXMLIOProcessor().close();
+ executor.addEvent(new EventBuilder("cancel.invoke."+ invokeId, TriggerEvent.CANCEL_EVENT).build());
}
}
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/b4a10313/src/main/java/org/apache/commons/scxml2/model/Action.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/model/Action.java b/src/main/java/org/apache/commons/scxml2/model/Action.java
index 550ddf0..0ad998b 100644
--- a/src/main/java/org/apache/commons/scxml2/model/Action.java
+++ b/src/main/java/org/apache/commons/scxml2/model/Action.java
@@ -126,8 +126,10 @@ public abstract class Action implements NamespacePrefixesHolder,
* a non-deterministic state.
* @throws SCXMLExpressionException If the execution involves trying
* to evaluate an expression which is malformed.
+ * @throws ActionExecutionError to be thrown if the execution caused an error (event) to be raised,
+ * which then shall stop execution of (possible) following actions within the same executable content block
*/
- public abstract void execute(ActionExecutionContext exctx) throws ModelException, SCXMLExpressionException;
+ public abstract void execute(ActionExecutionContext exctx) throws ModelException, SCXMLExpressionException, ActionExecutionError;
/**
* Return the key under which the current document namespaces are saved
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/b4a10313/src/main/java/org/apache/commons/scxml2/model/ActionExecutionError.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/model/ActionExecutionError.java b/src/main/java/org/apache/commons/scxml2/model/ActionExecutionError.java
new file mode 100644
index 0000000..a71e7ea
--- /dev/null
+++ b/src/main/java/org/apache/commons/scxml2/model/ActionExecutionError.java
@@ -0,0 +1,57 @@
+/*
+ * 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.scxml2.model;
+
+import org.apache.commons.scxml2.ActionExecutionContext;
+import org.apache.commons.scxml2.ErrorReporter;
+import org.apache.commons.scxml2.TriggerEvent;
+
+/**
+ * ActionExecutionError is a specific RuntimeException used for communicating the execution failure of an action.
+ * This exception when thrown from within {@link Action#execute(ActionExecutionContext)} will:
+ * <ul>
+ * <li>stop further execution of (possible) following action within the same executable content block</li>
+ * <li>if not yet {@link #isEventRaised()} raise the internal error event {@link TriggerEvent#ERROR_EXECUTION}</li>
+ * <li>if a non-null error message is provided with the exception, report an error message with {@link ErrorReporter}</li>
+ * </ul>
+ * @see <a href="https://www.w3.org/TR/2015/REC-scxml-20150901/#EvaluationofExecutableContent">SCXML spec 4.9 Evaluation of Executable Content</a>
+ */
+public final class ActionExecutionError extends RuntimeException {
+
+ private final boolean eventRaised;
+
+ public ActionExecutionError() {
+ this(false, null);
+ }
+
+ public ActionExecutionError(final boolean eventRaised) {
+ this(eventRaised, null);
+ }
+
+ public ActionExecutionError(final String message) {
+ this(false, message);
+ }
+
+ public ActionExecutionError(final boolean eventRaised, final String message) {
+ super(message);
+ this.eventRaised = eventRaised;
+ }
+
+ public boolean isEventRaised() {
+ return eventRaised;
+ }
+}
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/b4a10313/src/main/java/org/apache/commons/scxml2/model/Foreach.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/model/Foreach.java b/src/main/java/org/apache/commons/scxml2/model/Foreach.java
index 1325f79..6007b12 100644
--- a/src/main/java/org/apache/commons/scxml2/model/Foreach.java
+++ b/src/main/java/org/apache/commons/scxml2/model/Foreach.java
@@ -144,7 +144,9 @@ public class Foreach extends Action implements ActionsContainer {
}
}
}
- // else {} TODO: place the error 'error.execution' in the internal event queue. (section "3.12.2 Errors")
+ else {
+ throw new ActionExecutionError("<foreach> in state " + getParentEnterableState().getId()+": invalid array value '"+array+"'");
+ }
}
finally {
ctx.setLocal(getNamespacesKey(), null);
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/b4a10313/src/main/java/org/apache/commons/scxml2/model/If.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/model/If.java b/src/main/java/org/apache/commons/scxml2/model/If.java
index 7b93119..826afab 100644
--- a/src/main/java/org/apache/commons/scxml2/model/If.java
+++ b/src/main/java/org/apache/commons/scxml2/model/If.java
@@ -24,6 +24,7 @@ import org.apache.commons.scxml2.Context;
import org.apache.commons.scxml2.Evaluator;
import org.apache.commons.scxml2.SCXMLExpressionException;
import org.apache.commons.scxml2.TriggerEvent;
+import org.apache.commons.scxml2.EventBuilder;
import org.apache.commons.scxml2.semantics.ErrorConstants;
/**
@@ -132,7 +133,7 @@ public class If extends Action implements ActionsContainer {
}
} catch (SCXMLExpressionException e) {
rslt = Boolean.FALSE;
- exctx.getInternalIOProcessor().addEvent(new TriggerEvent(TriggerEvent.ERROR_EXECUTION, TriggerEvent.ERROR_EVENT));
+ exctx.getInternalIOProcessor().addEvent(new EventBuilder(TriggerEvent.ERROR_EXECUTION, TriggerEvent.ERROR_EVENT).build());
exctx.getErrorReporter().onError(ErrorConstants.EXPRESSION_ERROR, "Treating as false due to error: "
+ e.getMessage(), this);
}
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/b4a10313/src/main/java/org/apache/commons/scxml2/model/Invoke.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/model/Invoke.java b/src/main/java/org/apache/commons/scxml2/model/Invoke.java
index 4885cc7..c14985c 100644
--- a/src/main/java/org/apache/commons/scxml2/model/Invoke.java
+++ b/src/main/java/org/apache/commons/scxml2/model/Invoke.java
@@ -27,6 +27,7 @@ import org.apache.commons.scxml2.SCXMLExecutionContext;
import org.apache.commons.scxml2.SCXMLExpressionException;
import org.apache.commons.scxml2.SCXMLSystemContext;
import org.apache.commons.scxml2.TriggerEvent;
+import org.apache.commons.scxml2.EventBuilder;
import org.apache.commons.scxml2.invoke.Invoker;
import org.apache.commons.scxml2.invoke.InvokerException;
import org.apache.commons.scxml2.semantics.ErrorConstants;
@@ -103,6 +104,11 @@ public class Invoke extends NamelistHolder implements PathResolverHolder, Conten
private EnterableState parent;
/**
+ * This invoke index in the parent (TransitionalState) defined invokers
+ */
+ private int invokeIndex;
+
+ /**
* Get the identifier for this invoke (may be null).
*
* @return Returns the id.
@@ -322,14 +328,14 @@ public class Invoke extends NamelistHolder implements PathResolverHolder, Conten
* Set the parent EnterableState.
* @param parent The parent state to set
*/
- public void setParentEnterableState(final EnterableState parent) {
+ public void setParentEnterableState(final EnterableState parent, final int invokeIndex) {
if (parent == null) {
throw new IllegalArgumentException("Parent parameter cannot be null");
}
this.parent = parent;
+ this.invokeIndex = invokeIndex;
}
- @SuppressWarnings("unchecked")
@Override
public void execute(final ActionExecutionContext axctx) throws ModelException {
EnterableState parentState = getParentEnterableState();
@@ -357,7 +363,7 @@ public class Invoke extends NamelistHolder implements PathResolverHolder, Conten
String invokeId = getId();
if (invokeId == null) {
- invokeId = parentState.getId() + "." + ctx.get(SCXMLSystemContext.SESSIONID_KEY);
+ invokeId = parentState.getId() + "." + ctx.get(SCXMLSystemContext.SESSIONID_KEY) + "." + invokeIndex;
}
if (getId() == null && getIdlocation() != null) {
eval.evalAssign(ctx, idlocation, invokeId);
@@ -390,7 +396,7 @@ public class Invoke extends NamelistHolder implements PathResolverHolder, Conten
}
}
if (src == null && srcNode == null) {
- throw new SCXMLExpressionException("<invoke> for state "+parentState.getId() +
+ throw new ActionExecutionError("<invoke> for state "+parentState.getId() +
": no src and no content defined");
}
Map<String, Object> payloadDataMap = new HashMap<>();
@@ -403,13 +409,12 @@ public class Invoke extends NamelistHolder implements PathResolverHolder, Conten
// TODO: } else { invoker.invoke(srcNode, payloadDataMap); }
exctx.registerInvoker(this, invoker);
}
- catch (InvokerException e) {
- axctx.getErrorReporter().onError(ErrorConstants.EXECUTION_ERROR, e.getMessage(), this);
- axctx.getInternalIOProcessor().addEvent(new TriggerEvent(TriggerEvent.ERROR_EXECUTION, TriggerEvent.ERROR_EVENT));
- }
- catch (SCXMLExpressionException e) {
- axctx.getInternalIOProcessor().addEvent(new TriggerEvent(TriggerEvent.ERROR_EXECUTION, TriggerEvent.ERROR_EVENT));
- axctx.getErrorReporter().onError(ErrorConstants.EXPRESSION_ERROR, e.getMessage(), this);
+ catch (InvokerException|ActionExecutionError|SCXMLExpressionException e) {
+ axctx.getInternalIOProcessor().addEvent(new EventBuilder(TriggerEvent.ERROR_EXECUTION, TriggerEvent.ERROR_EVENT).build());
+ if (e.getMessage() != null) {
+ axctx.getErrorReporter().onError(e instanceof SCXMLExpressionException
+ ? ErrorConstants.EXPRESSION_ERROR : ErrorConstants.EXECUTION_ERROR, e.getMessage(), this);
+ }
}
finally {
ctx.setLocal(getNamespacesKey(), null);
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/b4a10313/src/main/java/org/apache/commons/scxml2/model/Raise.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/model/Raise.java b/src/main/java/org/apache/commons/scxml2/model/Raise.java
index ab85606..9fa2aad 100644
--- a/src/main/java/org/apache/commons/scxml2/model/Raise.java
+++ b/src/main/java/org/apache/commons/scxml2/model/Raise.java
@@ -19,6 +19,7 @@ package org.apache.commons.scxml2.model;
import org.apache.commons.scxml2.ActionExecutionContext;
import org.apache.commons.scxml2.SCXMLExpressionException;
import org.apache.commons.scxml2.TriggerEvent;
+import org.apache.commons.scxml2.EventBuilder;
/**
* The class in this SCXML object model that corresponds to the
@@ -72,7 +73,7 @@ public class Raise extends Action {
if (exctx.getAppLog().isDebugEnabled()) {
exctx.getAppLog().debug("<raise>: Adding event '" + event + "' to list of derived events.");
}
- TriggerEvent ev = new TriggerEvent(event, TriggerEvent.SIGNAL_EVENT);
+ TriggerEvent ev = new EventBuilder(event, TriggerEvent.SIGNAL_EVENT).build();
exctx.getInternalIOProcessor().addEvent(ev);
}
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/b4a10313/src/main/java/org/apache/commons/scxml2/model/Send.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/model/Send.java b/src/main/java/org/apache/commons/scxml2/model/Send.java
index 3352056..b7ed695 100644
--- a/src/main/java/org/apache/commons/scxml2/model/Send.java
+++ b/src/main/java/org/apache/commons/scxml2/model/Send.java
@@ -346,87 +346,91 @@ public class Send extends NamelistHolder implements ContentContainer {
// Send attributes evaluation
EnterableState parentState = getParentEnterableState();
Context ctx = exctx.getContext(parentState);
- ctx.setLocal(getNamespacesKey(), getNamespaces());
- Evaluator eval = exctx.getEvaluator();
- // Most attributes of <send> are expressions so need to be
- // evaluated before the EventDispatcher callback
- Object hintsValue = null;
- if (hints != null) {
- hintsValue = eval.eval(ctx, hints);
- }
- if (id == null) {
- id = ctx.getSystemContext().generateSessionId();
+ try {
+ ctx.setLocal(getNamespacesKey(), getNamespaces());
+ Evaluator eval = exctx.getEvaluator();
+ // Most attributes of <send> are expressions so need to be
+ // evaluated before the EventDispatcher callback
+ Object hintsValue = null;
+ if (hints != null) {
+ hintsValue = eval.eval(ctx, hints);
+ }
if (idlocation != null) {
+ if (id == null) {
+ id = ctx.getSystemContext().generateSessionId();
+ }
eval.evalAssign(ctx, idlocation, id);
}
- }
- String targetValue = target;
- if (targetValue == null && targetexpr != null) {
- targetValue = (String)eval.eval(ctx, targetexpr);
- if ((targetValue == null || targetValue.trim().length() == 0)
- && exctx.getAppLog().isWarnEnabled()) {
- exctx.getAppLog().warn("<send>: target expression \"" + targetexpr
- + "\" evaluated to null or empty String");
+ String targetValue = target;
+ if (targetValue == null && targetexpr != null) {
+ targetValue = (String)eval.eval(ctx, targetexpr);
+ if ((targetValue == null || targetValue.trim().length() == 0)
+ && exctx.getAppLog().isWarnEnabled()) {
+ exctx.getAppLog().warn("<send>: target expression \"" + targetexpr
+ + "\" evaluated to null or empty String");
+ }
}
- }
- String typeValue = type;
- if (typeValue == null && typeexpr != null) {
- typeValue = (String)eval.eval(ctx, typeexpr);
- if ((typeValue == null || typeValue.trim().length() == 0)
- && exctx.getAppLog().isWarnEnabled()) {
- exctx.getAppLog().warn("<send>: type expression \"" + typeexpr
- + "\" evaluated to null or empty String");
+ String typeValue = type;
+ if (typeValue == null && typeexpr != null) {
+ typeValue = (String)eval.eval(ctx, typeexpr);
+ if ((typeValue == null || typeValue.trim().length() == 0)
+ && exctx.getAppLog().isWarnEnabled()) {
+ exctx.getAppLog().warn("<send>: type expression \"" + typeexpr
+ + "\" evaluated to null or empty String");
+ }
}
- }
- if (typeValue == null) {
- // must default to 'scxml' when unspecified
- typeValue = SCXMLIOProcessor.DEFAULT_EVENT_PROCESSOR;
- } else if (!SCXMLIOProcessor.DEFAULT_EVENT_PROCESSOR.equals(typeValue) && typeValue.trim().equalsIgnoreCase(SCXMLIOProcessor.SCXML_EVENT_PROCESSOR)) {
- typeValue = SCXMLIOProcessor.DEFAULT_EVENT_PROCESSOR;
- }
- Object payload = null;
- Map<String, Object> payloadDataMap = new LinkedHashMap<>();
- addNamelistDataToPayload(exctx, payloadDataMap);
- addParamsToPayload(exctx, payloadDataMap);
- if (!payloadDataMap.isEmpty()) {
- payload = payloadDataMap;
- }
- else if (content != null) {
- if (content.getExpr() != null) {
- payload = eval.cloneData(eval.eval(ctx, content.getExpr()));
- } else {
- payload = eval.cloneData(content.getBody());
+ if (typeValue == null) {
+ // must default to 'scxml' when unspecified
+ typeValue = SCXMLIOProcessor.DEFAULT_EVENT_PROCESSOR;
+ } else if (!SCXMLIOProcessor.DEFAULT_EVENT_PROCESSOR.equals(typeValue) && typeValue.trim().equalsIgnoreCase(SCXMLIOProcessor.SCXML_EVENT_PROCESSOR)) {
+ typeValue = SCXMLIOProcessor.DEFAULT_EVENT_PROCESSOR;
}
- }
- long wait = 0L;
- String delayString = delay;
- if (delayString == null && delayexpr != null) {
- Object delayValue = eval.eval(ctx, delayexpr);
- if (delayValue != null) {
- delayString = delayValue.toString();
+ Object payload = null;
+ Map<String, Object> payloadDataMap = new LinkedHashMap<>();
+ addNamelistDataToPayload(exctx, payloadDataMap);
+ addParamsToPayload(exctx, payloadDataMap);
+ if (!payloadDataMap.isEmpty()) {
+ payload = payloadDataMap;
}
- }
- if (delayString != null) {
- wait = parseDelay(delayString, delayexpr != null, delayexpr != null ? delayexpr : delay);
- }
- String eventValue = event;
- if (eventValue == null && eventexpr != null) {
- eventValue = (String)eval.eval(ctx, eventexpr);
- if ((eventValue == null)) {
- throw new SCXMLExpressionException("<send>: event expression \"" + eventexpr
- + "\" evaluated to null");
+ else if (content != null) {
+ if (content.getExpr() != null) {
+ payload = eval.cloneData(eval.eval(ctx, content.getExpr()));
+ } else {
+ payload = eval.cloneData(content.getBody());
+ }
+ }
+ long wait = 0L;
+ String delayString = delay;
+ if (delayString == null && delayexpr != null) {
+ Object delayValue = eval.eval(ctx, delayexpr);
+ if (delayValue != null) {
+ delayString = delayValue.toString();
+ }
+ }
+ if (delayString != null) {
+ wait = parseDelay(delayString, delayexpr != null, delayexpr != null ? delayexpr : delay);
+ }
+ String eventValue = event;
+ if (eventValue == null && eventexpr != null) {
+ eventValue = (String)eval.eval(ctx, eventexpr);
+ if ((eventValue == null)) {
+ throw new SCXMLExpressionException("<send>: event expression \"" + eventexpr
+ + "\" evaluated to null");
+ }
+ }
+ Map<String, SCXMLIOProcessor> ioProcessors = (Map<String, SCXMLIOProcessor>) ctx.get(SCXMLSystemContext.IOPROCESSORS_KEY);
+ if (exctx.getAppLog().isDebugEnabled()) {
+ exctx.getAppLog().debug("<send>: Dispatching event '" + eventValue
+ + "' to target '" + targetValue + "' of target type '"
+ + typeValue + "' with suggested delay of " + wait
+ + "ms");
}
+ exctx.getEventDispatcher().send(ioProcessors, id, targetValue, typeValue, eventValue,
+ payload, hintsValue, wait);
}
- Map<String, SCXMLIOProcessor> ioProcessors = (Map<String, SCXMLIOProcessor>) ctx.get(SCXMLSystemContext.IOPROCESSORS_KEY);
- ctx.setLocal(getNamespacesKey(), null);
- if (exctx.getAppLog().isDebugEnabled()) {
- exctx.getAppLog().debug("<send>: Dispatching event '" + eventValue
- + "' to target '" + targetValue + "' of target type '"
- + typeValue + "' with suggested delay of " + wait
- + "ms");
+ finally {
+ ctx.setLocal(getNamespacesKey(), null);
}
- exctx.getEventDispatcher().send(ioProcessors, id, targetValue, typeValue, eventValue,
- payload, hintsValue, wait);
}
/**
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/b4a10313/src/main/java/org/apache/commons/scxml2/model/TransitionalState.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/model/TransitionalState.java b/src/main/java/org/apache/commons/scxml2/model/TransitionalState.java
index c2f4f0a..e7adfd0 100644
--- a/src/main/java/org/apache/commons/scxml2/model/TransitionalState.java
+++ b/src/main/java/org/apache/commons/scxml2/model/TransitionalState.java
@@ -216,8 +216,8 @@ public abstract class TransitionalState extends EnterableState {
* The invoke to set.
*/
public final void addInvoke(final Invoke invoke) {
+ invoke.setParentEnterableState(this, this.invokes.size());
this.invokes.add(invoke);
- invoke.setParentEnterableState(this);
}
/**
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/b4a10313/src/main/java/org/apache/commons/scxml2/model/Var.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/model/Var.java b/src/main/java/org/apache/commons/scxml2/model/Var.java
index a08c23e..71191d5 100644
--- a/src/main/java/org/apache/commons/scxml2/model/Var.java
+++ b/src/main/java/org/apache/commons/scxml2/model/Var.java
@@ -21,6 +21,7 @@ import org.apache.commons.scxml2.Context;
import org.apache.commons.scxml2.Evaluator;
import org.apache.commons.scxml2.SCXMLExpressionException;
import org.apache.commons.scxml2.TriggerEvent;
+import org.apache.commons.scxml2.EventBuilder;
/**
* The class in this SCXML object model that corresponds to the
@@ -104,7 +105,7 @@ public class Var extends Action {
exctx.getAppLog().debug("<var>: Defined variable '" + name
+ "' with initial value '" + String.valueOf(varObj) + "'");
}
- TriggerEvent ev = new TriggerEvent(name + ".change", TriggerEvent.CHANGE_EVENT);
+ TriggerEvent ev = new EventBuilder(name + ".change", TriggerEvent.CHANGE_EVENT).build();
exctx.getInternalIOProcessor().addEvent(ev);
}
}
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/b4a10313/src/main/java/org/apache/commons/scxml2/semantics/SCXMLSemanticsImpl.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/semantics/SCXMLSemanticsImpl.java b/src/main/java/org/apache/commons/scxml2/semantics/SCXMLSemanticsImpl.java
index 0278832..4e476c2 100644
--- a/src/main/java/org/apache/commons/scxml2/semantics/SCXMLSemanticsImpl.java
+++ b/src/main/java/org/apache/commons/scxml2/semantics/SCXMLSemanticsImpl.java
@@ -28,6 +28,7 @@ import java.util.Set;
import org.apache.commons.scxml2.ActionExecutionContext;
import org.apache.commons.scxml2.Context;
import org.apache.commons.scxml2.ErrorReporter;
+import org.apache.commons.scxml2.ParentSCXMLIOProcessor;
import org.apache.commons.scxml2.SCInstance;
import org.apache.commons.scxml2.SCXMLExecutionContext;
import org.apache.commons.scxml2.SCXMLExpressionException;
@@ -35,9 +36,10 @@ import org.apache.commons.scxml2.SCXMLSemantics;
import org.apache.commons.scxml2.SCXMLSystemContext;
import org.apache.commons.scxml2.StateConfiguration;
import org.apache.commons.scxml2.TriggerEvent;
-import org.apache.commons.scxml2.invoke.Invoker;
+import org.apache.commons.scxml2.EventBuilder;
import org.apache.commons.scxml2.invoke.InvokerException;
import org.apache.commons.scxml2.model.Action;
+import org.apache.commons.scxml2.model.ActionExecutionError;
import org.apache.commons.scxml2.model.DocumentOrder;
import org.apache.commons.scxml2.model.EnterableState;
import org.apache.commons.scxml2.model.Executable;
@@ -222,7 +224,18 @@ public class SCXMLSemanticsImpl implements SCXMLSemantics {
}
exctx.getNotificationRegistry().fireOnExit(es, es);
exctx.getNotificationRegistry().fireOnExit(exctx.getStateMachine(), es);
- if (!(es instanceof Final && es.getParent() == null)) {
+ if (es instanceof Final && es.getParent() == null) {
+ if (exctx.getSCXMLExecutor().getParentSCXMLIOProcessor() != null) {
+ ParentSCXMLIOProcessor ioProcessor = exctx.getSCXMLExecutor().getParentSCXMLIOProcessor();
+ if (!ioProcessor.isClosed()) {
+ ioProcessor.addEvent(
+ new EventBuilder("done.invoke."+ioProcessor.getInvokeId(), TriggerEvent.SIGNAL_EVENT)
+ .invokeId(ioProcessor.getInvokeId()).build());
+ ioProcessor.close();
+ }
+ }
+ }
+ else {
exctx.getScInstance().getStateConfiguration().exitState(es);
}
// else: keep final Final
@@ -707,7 +720,7 @@ public class SCXMLSemanticsImpl implements SCXMLSemantics {
}
}
catch (SCXMLExpressionException e) {
- exctx.getInternalIOProcessor().addEvent(new TriggerEvent(TriggerEvent.ERROR_EXECUTION, TriggerEvent.ERROR_EVENT));
+ exctx.getInternalIOProcessor().addEvent(new EventBuilder(TriggerEvent.ERROR_EXECUTION, TriggerEvent.ERROR_EVENT).build());
exctx.getErrorReporter().onError(ErrorConstants.EXPRESSION_ERROR, "Treating as false due to error: "
+ e.getMessage(), transition);
}
@@ -747,19 +760,6 @@ public class SCXMLSemanticsImpl implements SCXMLSemantics {
}
/**
- * Checks if an external event was send (back) by an specific Invoker
- *
- * @param invokerId the invokerId
- *
- * @param event received external event
- * @return true if this event was send by the specific Invoker
- */
- public boolean isInvokerEvent(final String invokerId, final TriggerEvent event) {
- return event.getName().equals("done.invoke."+invokerId) ||
- event.getName().startsWith("done.invoke."+invokerId+".");
- }
-
- /**
* Check if an external event indicates the state machine execution must be cancelled.
*
* @param event received external event
@@ -854,9 +854,8 @@ public class SCXMLSemanticsImpl implements SCXMLSemantics {
if (triggerEventType == TriggerEvent.ERROR_EVENT || triggerEventType == TriggerEvent.CHANGE_EVENT) {
eventType = EventVariable.TYPE_PLATFORM;
}
-
- // TODO: determine sendid, origin, originType and invokeid based on context later.
- eventVar = new EventVariable(event.getName(), eventType, null, null, null, null, event.getPayload());
+ eventVar = new EventVariable(event.getName(), eventType, event.getSendId(), event.getOrigin(),
+ event.getOriginType(), event.getInvokeId(), event.getData());
}
systemContext.setLocal(SCXMLSystemContext.EVENT_KEY, eventVar);
}
@@ -873,7 +872,7 @@ public class SCXMLSemanticsImpl implements SCXMLSemantics {
try {
globalScript.execute(exctx.getActionExecutionContext());
} catch (SCXMLExpressionException e) {
- exctx.getInternalIOProcessor().addEvent(new TriggerEvent(TriggerEvent.ERROR_EXECUTION, TriggerEvent.ERROR_EVENT));
+ exctx.getInternalIOProcessor().addEvent(new EventBuilder(TriggerEvent.ERROR_EXECUTION, TriggerEvent.ERROR_EVENT).build());
exctx.getErrorReporter().onError(ErrorConstants.EXPRESSION_ERROR, e.getMessage(), exctx.getStateMachine());
}
}
@@ -912,7 +911,7 @@ public class SCXMLSemanticsImpl implements SCXMLSemantics {
executeContent(exctx, onexit);
if (!onexitEventRaised && onexit.isRaiseEvent()) {
onexitEventRaised = true;
- exctx.getInternalIOProcessor().addEvent(new TriggerEvent("exit.state."+es.getId(), TriggerEvent.CHANGE_EVENT));
+ exctx.getInternalIOProcessor().addEvent(new EventBuilder("exit.state."+es.getId(), TriggerEvent.CHANGE_EVENT).build());
}
}
exctx.getNotificationRegistry().fireOnExit(es, es);
@@ -954,8 +953,15 @@ public class SCXMLSemanticsImpl implements SCXMLSemantics {
action.execute(exctx.getActionExecutionContext());
}
} catch (SCXMLExpressionException e) {
- exctx.getInternalIOProcessor().addEvent(new TriggerEvent(TriggerEvent.ERROR_EXECUTION, TriggerEvent.ERROR_EVENT));
+ exctx.getInternalIOProcessor().addEvent(new EventBuilder(TriggerEvent.ERROR_EXECUTION, TriggerEvent.ERROR_EVENT).build());
exctx.getErrorReporter().onError(ErrorConstants.EXPRESSION_ERROR, e.getMessage(), exec);
+ } catch (ActionExecutionError e) {
+ if (!e.isEventRaised()) {
+ exctx.getInternalIOProcessor().addEvent(new EventBuilder(TriggerEvent.ERROR_EXECUTION, TriggerEvent.ERROR_EVENT).build());
+ }
+ if (e.getMessage() != null) {
+ exctx.getErrorReporter().onError(ErrorConstants.EXECUTION_ERROR, e.getMessage(), exec);
+ }
}
if (exec instanceof Transition) {
Transition t = (Transition)exec;
@@ -1016,7 +1022,7 @@ public class SCXMLSemanticsImpl implements SCXMLSemantics {
executeContent(exctx, onentry);
if (!onentryEventRaised && onentry.isRaiseEvent()) {
onentryEventRaised = true;
- exctx.getInternalIOProcessor().addEvent(new TriggerEvent("entry.state."+es.getId(), TriggerEvent.CHANGE_EVENT));
+ exctx.getInternalIOProcessor().addEvent(new EventBuilder("entry.state."+es.getId(), TriggerEvent.CHANGE_EVENT).build());
}
}
exctx.getNotificationRegistry().fireOnEntry(es, es);
@@ -1038,11 +1044,11 @@ public class SCXMLSemanticsImpl implements SCXMLSemantics {
exctx.stop();
}
else {
- exctx.getInternalIOProcessor().addEvent(new TriggerEvent("done.state."+parent.getId(),TriggerEvent.CHANGE_EVENT));
+ exctx.getInternalIOProcessor().addEvent(new EventBuilder("done.state."+parent.getId(),TriggerEvent.CHANGE_EVENT).build());
if (parent.isRegion()) {
if (isInFinalState(parent.getParent(), exctx.getScInstance().getStateConfiguration().getActiveStates())) {
- exctx.getInternalIOProcessor().addEvent(new TriggerEvent("done.state."+parent.getParent().getId()
- , TriggerEvent.CHANGE_EVENT));
+ exctx.getInternalIOProcessor().addEvent(new EventBuilder("done.state."+parent.getParent().getId()
+ , TriggerEvent.CHANGE_EVENT).build());
}
}
}
@@ -1081,11 +1087,13 @@ public class SCXMLSemanticsImpl implements SCXMLSemantics {
*/
public void processInvokes(final SCXMLExecutionContext exctx, final TriggerEvent event) throws ModelException {
for (Map.Entry<Invoke, String> entry : exctx.getInvokeIds().entrySet()) {
- if (!isInvokerEvent(entry.getValue(), event)) {
- if (entry.getKey().isAutoForward()) {
- Invoker inv = exctx.getInvoker(entry.getKey());
+ if (entry.getValue().equals(event.getInvokeId())) {
+ Invoke invoke = entry.getKey();
+ if (entry.getKey().isAutoForward() &&
+ !(event.getName().equals("done.invoke."+entry.getValue()) ||
+ event.getName().startsWith("done.invoke."+entry.getValue()+"."))) {
try {
- inv.parentEvent(event);
+ exctx.getInvoker(entry.getKey()).parentEvent(event);
} catch (InvokerException ie) {
exctx.getAppLog().error(ie.getMessage(), ie);
throw new ModelException(ie.getMessage(), ie.getCause());
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/b4a10313/src/main/java/org/apache/commons/scxml2/system/EventVariable.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/system/EventVariable.java b/src/main/java/org/apache/commons/scxml2/system/EventVariable.java
index edaa1c3..13800aa 100644
--- a/src/main/java/org/apache/commons/scxml2/system/EventVariable.java
+++ b/src/main/java/org/apache/commons/scxml2/system/EventVariable.java
@@ -104,5 +104,25 @@ public class EventVariable implements Serializable {
public Object getData() {
return data;
}
+
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("_event(");
+ sb.append("name: ").append(name);
+ sb.append(", type: ").append(type);
+ if (sendid != null) {
+ sb.append(", sendid: ").append(sendid);
+ }
+ if (origin != null) {
+ sb.append(", origin: ").append(origin);
+ }
+ if (origintype != null) {
+ sb.append(", origintype: ").append(origintype);
+ }
+ if (invokeid != null) {
+ sb.append(", invokeid: ").append(invokeid);
+ }
+ sb.append(")");
+ return sb.toString();
+ }
}
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/b4a10313/src/main/java/org/apache/commons/scxml2/test/StandaloneUtils.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/scxml2/test/StandaloneUtils.java b/src/main/java/org/apache/commons/scxml2/test/StandaloneUtils.java
index 91db521..12c860e 100644
--- a/src/main/java/org/apache/commons/scxml2/test/StandaloneUtils.java
+++ b/src/main/java/org/apache/commons/scxml2/test/StandaloneUtils.java
@@ -29,6 +29,7 @@ import org.apache.commons.scxml2.Context;
import org.apache.commons.scxml2.Evaluator;
import org.apache.commons.scxml2.SCXMLExecutor;
import org.apache.commons.scxml2.TriggerEvent;
+import org.apache.commons.scxml2.EventBuilder;
import org.apache.commons.scxml2.env.Tracer;
import org.apache.commons.scxml2.invoke.SimpleSCXMLInvoker;
import org.apache.commons.scxml2.io.SCXMLReader;
@@ -111,8 +112,7 @@ public final class StandaloneUtils {
+ value);
} else if (event.trim().length() == 0
|| event.equalsIgnoreCase("null")) {
- TriggerEvent[] evts = {new TriggerEvent(null,
- TriggerEvent.SIGNAL_EVENT, null)};
+ TriggerEvent[] evts = {new EventBuilder(null,TriggerEvent.SIGNAL_EVENT).build()};
exec.triggerEvents(evts);
if (exec.getStatus().isFinal()) {
System.out.println("A final configuration reached.");
@@ -122,8 +122,7 @@ public final class StandaloneUtils {
int tkns = st.countTokens();
TriggerEvent[] evts = new TriggerEvent[tkns];
for (int i = 0; i < tkns; i++) {
- evts[i] = new TriggerEvent(st.nextToken(),
- TriggerEvent.SIGNAL_EVENT, null);
+ evts[i] = new EventBuilder(st.nextToken(), TriggerEvent.SIGNAL_EVENT).build();
}
exec.triggerEvents(evts);
if (exec.getStatus().isFinal()) {
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/b4a10313/src/test/java/org/apache/commons/scxml2/EventDataTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/scxml2/EventDataTest.java b/src/test/java/org/apache/commons/scxml2/EventDataTest.java
index fe92acc..885c182 100644
--- a/src/test/java/org/apache/commons/scxml2/EventDataTest.java
+++ b/src/test/java/org/apache/commons/scxml2/EventDataTest.java
@@ -39,19 +39,16 @@ public class EventDataTest {
Set<EnterableState> currentStates = exec.getStatus().getStates();
Assert.assertEquals(1, currentStates.size());
Assert.assertEquals("state1", currentStates.iterator().next().getId());
- TriggerEvent te = new TriggerEvent("event.foo",
- TriggerEvent.SIGNAL_EVENT, new Integer(3));
+ TriggerEvent te = new EventBuilder("event.foo", TriggerEvent.SIGNAL_EVENT).data(new Integer(3)).build();
currentStates = SCXMLTestHelper.fireEvent(exec, te);
Assert.assertEquals(1, currentStates.size());
Assert.assertEquals("state3", currentStates.iterator().next().getId());
TriggerEvent[] evts = new TriggerEvent[] { te,
- new TriggerEvent("event.bar", TriggerEvent.SIGNAL_EVENT,
- new Integer(6))};
+ new EventBuilder("event.bar", TriggerEvent.SIGNAL_EVENT).data(new Integer(6)).build()};
currentStates = SCXMLTestHelper.fireEvents(exec, evts);
Assert.assertEquals(1, currentStates.size());
Assert.assertEquals("state6", currentStates.iterator().next().getId());
- te = new TriggerEvent("event.baz",
- TriggerEvent.SIGNAL_EVENT, new Integer(7));
+ te = new EventBuilder("event.baz", TriggerEvent.SIGNAL_EVENT).data(new Integer(7)).build();
currentStates = SCXMLTestHelper.fireEvent(exec, te);
Assert.assertEquals(1, currentStates.size());
Assert.assertEquals("state7", currentStates.iterator().next().getId());
@@ -64,14 +61,12 @@ public class EventDataTest {
Set<EnterableState> currentStates = exec.getStatus().getStates();
Assert.assertEquals(1, currentStates.size());
Assert.assertEquals("state0", currentStates.iterator().next().getId());
- TriggerEvent te1 = new TriggerEvent("connection.alerting",
- TriggerEvent.SIGNAL_EVENT, "line2");
+ TriggerEvent te1 = new EventBuilder("connection.alerting", TriggerEvent.SIGNAL_EVENT).data("line2").build();
currentStates = SCXMLTestHelper.fireEvent(exec, te1);
Assert.assertEquals(1, currentStates.size());
Assert.assertEquals("state2", currentStates.iterator().next().getId());
- TriggerEvent te2 = new TriggerEvent("connection.alerting",
- TriggerEvent.SIGNAL_EVENT,
- new ConnectionAlertingPayload(4));
+ TriggerEvent te2 = new EventBuilder("connection.alerting", TriggerEvent.SIGNAL_EVENT)
+ .data(new ConnectionAlertingPayload(4)).build();
currentStates = SCXMLTestHelper.fireEvent(exec, te2);
Assert.assertEquals(1, currentStates.size());
Assert.assertEquals("state4", currentStates.iterator().next().getId());
@@ -84,8 +79,7 @@ public class EventDataTest {
Set<EnterableState> currentStates = exec.getStatus().getStates();
Assert.assertEquals(1, currentStates.size());
Assert.assertEquals("ten", currentStates.iterator().next().getId());
- TriggerEvent te = new TriggerEvent("event.foo",
- TriggerEvent.SIGNAL_EVENT);
+ TriggerEvent te = new EventBuilder("event.foo", TriggerEvent.SIGNAL_EVENT).build();
currentStates = SCXMLTestHelper.fireEvent(exec, te);
Assert.assertEquals(1, currentStates.size());
Assert.assertEquals("thirty", currentStates.iterator().next().getId());
http://git-wip-us.apache.org/repos/asf/commons-scxml/blob/b4a10313/src/test/java/org/apache/commons/scxml2/SCXMLTestHelper.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/scxml2/SCXMLTestHelper.java b/src/test/java/org/apache/commons/scxml2/SCXMLTestHelper.java
index 983bc7c..fef7a9d 100644
--- a/src/test/java/org/apache/commons/scxml2/SCXMLTestHelper.java
+++ b/src/test/java/org/apache/commons/scxml2/SCXMLTestHelper.java
@@ -148,8 +148,8 @@ public class SCXMLTestHelper {
return fireEvent(exec, name, null);
}
- public static Set<EnterableState> fireEvent(SCXMLExecutor exec, String name, Object payload) throws Exception {
- TriggerEvent[] evts = {new TriggerEvent(name, TriggerEvent.SIGNAL_EVENT, payload)};
+ public static Set<EnterableState> fireEvent(SCXMLExecutor exec, String name, Object data) throws Exception {
+ TriggerEvent[] evts = {new EventBuilder(name, TriggerEvent.SIGNAL_EVENT).data(data).build()};
exec.triggerEvents(evts);
return exec.getStatus().getStates();
}
@@ -170,9 +170,9 @@ public class SCXMLTestHelper {
}
public static void assertPostTriggerState(SCXMLExecutor exec,
- String triggerEventName, Object payload, String expectedStateId) throws Exception {
- assertPostTriggerState(exec, new TriggerEvent(triggerEventName,
- TriggerEvent.SIGNAL_EVENT, payload), expectedStateId);
+ String triggerEventName, Object data, String expectedStateId) throws Exception {
+ assertPostTriggerState(exec, new EventBuilder(triggerEventName, TriggerEvent.SIGNAL_EVENT)
+ .data(data).build(), expectedStateId);
}
public static void assertPostTriggerStates(SCXMLExecutor exec,
@@ -181,9 +181,9 @@ public class SCXMLTestHelper {
}
public static void assertPostTriggerStates(SCXMLExecutor exec,
- String triggerEventName, Object payload, String[] expectedStateIds) throws Exception {
- assertPostTriggerStates(exec, new TriggerEvent(triggerEventName,
- TriggerEvent.SIGNAL_EVENT, payload), expectedStateIds);
+ String triggerEventName, Object data, String[] expectedStateIds) throws Exception {
+ assertPostTriggerStates(exec, new EventBuilder(triggerEventName, TriggerEvent.SIGNAL_EVENT)
+ .data(data).build(), expectedStateIds);
}
public static void assertPostTriggerState(SCXMLExecutor exec,