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 <a...@apache.org> Authored: Sun Dec 10 04:04:13 2017 +0100 Committer: Ate Douma <a...@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,