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 2014/04/03 09:13:44 UTC
svn commit: r1584272 [2/6] - in /commons/proper/scxml/trunk/src:
main/java/org/apache/commons/scxml2/ main/java/org/apache/commons/scxml2/env/
main/java/org/apache/commons/scxml2/env/groovy/
main/java/org/apache/commons/scxml2/env/javascript/ main/java...
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLSemantics.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLSemantics.java?rev=1584272&r1=1584271&r2=1584272&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLSemantics.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLSemantics.java Thu Apr 3 07:13:42 2014
@@ -24,10 +24,44 @@ import org.apache.commons.scxml2.model.S
* <a href="http://www.w3.org/TR/2014/CR-scxml-20140313/#AlgorithmforSCXMLInterpretation">
* W3C SCXML Algorithm for SCXML Interpretation</a>
* from the <code>SCXMLExecutor</code> and therefore make it pluggable.</p>
- *
- * <p>Semantics agnostic utility functions and common operators as defined in
- * UML can be found in the <code>SCXMLHelper</code> or attached directly to
- * the SCXML model elements.</p>
+ * <p>
+ * From an SCXML execution POV, there are only three entry points needed into the Algorithm, namely:
+ * <ul>
+ * <li>Performing the initialization of the state machine and completing a first macro step,
+ * see: {@link #firstStep(SCXMLExecutionContext)}. The state machine thereafter should be ready
+ * for processing external events (or be terminated already)</li>
+ * <li>Processing a single external event and completing the macro step for it, after which the
+ * state machine should be ready for processing another external event (if any), or be terminated already.
+ * See: {@link #nextStep(SCXMLExecutionContext, TriggerEvent)}.
+ * </li>
+ * <li>Finally, if the state machine terminated ({@link SCXMLExecutionContext#isRunning()} == false), after either
+ * of the above steps, finalize the state machine by performing the final step.
+ * See: {@link #finalStep(SCXMLExecutionContext)}.
+ * </li>
+ * </ul>
+ * </p>
+ * <p>After a state machine has been terminated you can re-initialize the execution context, and start again.</p>
+ * <p>
+ * Except for the loading of the SCXML document and (re)initializing the {@link SCXMLExecutionContext}, the above steps
+ * represent the <b>interpret</b>,<b>mainEventLoop</b> and <b>exitInterpreter</b> entry points specified in Algorithm
+ * for SCXML Interpretation, but more practically and logically broken into separate steps so that the blocking wait
+ * for external events can be handled externally.
+ * </p>
+ * <p>
+ * These three entry points are the only interface methods used by the SCXMLExecutor. It is up to the
+ * specific SCXMLSemantics implementation to provide the concrete handling for these according to the Algorithm in
+ * the SCXML specification (or possibly something else/different).
+ * </p>
+ * <p>
+ * The default {@link org.apache.commons.scxml2.semantics.SCXMLSemanticsImpl} provides an implementation of the
+ * specification, and can easily be overridden/customized as a whole or only on specific parts of the Algorithm
+ * implementation.
+ * </p>
+ * <p>
+ * Note that both the {@link #firstStep(SCXMLExecutionContext)} and {@link #nextStep(SCXMLExecutionContext, TriggerEvent)}
+ * first run to completion for any internal events raised before returning, as expected and required by the SCXML
+ * specification, so it is currently not possible to 'manage' internal event processing externally.
+ * </p>
*
* <p>Specific semantics can be created by subclassing
* <code>org.apache.commons.scxml2.semantics.SCXMLSemanticsImpl</code>.</p>
@@ -44,89 +78,76 @@ public interface SCXMLSemantics {
*/
SCXML normalizeStateMachine(final SCXML input, final ErrorReporter errRep);
- public void executeGlobalScript(final SCXMLExecutionContext context, final Step step) throws ModelException;
-
- public void exitStates(final SCXMLExecutionContext ctx, final Step step) throws ModelException;
-
- public void executeTransitionContent(final SCXMLExecutionContext ctx, final Step step) throws ModelException;
-
- public void enterStates(final SCXMLExecutionContext ctx, final Step step) throws ModelException;
-
- /**
- * Determining the initial state(s) for this state machine.
- *
- * @param ctx provides the execution context
- * @param step provides target states and entry list to fill in [out]
- *
- * @throws org.apache.commons.scxml2.model.ModelException in case there is a fatal SCXML object model problem.
- */
- void determineInitialStates(final SCXMLExecutionContext ctx, final Step step) throws ModelException;
-
- /**
- * Executes all OnExit/Transition/OnEntry transitional actions.
- *
- * @param ctx provides the execution context
- * @param step provides EntryList, TransitList, ExitList gets updated its AfterStatus/Events
- *
- * @throws org.apache.commons.scxml2.model.ModelException in case there is a fatal SCXML object model problem.
- */
- void executeActions(final SCXMLExecutionContext ctx, final Step step) throws ModelException;
-
- /**
- * Enumerate all the reachable transitions.
- *
- * @param ctx provides the execution context
- * @param step with current status and list of transitions to populate
- */
- void enumerateReachableTransitions(final SCXMLExecutionContext ctx, final Step step);
-
- /**
- * Filter the transitions set, eliminate those whose guard conditions
- * are not satisfied.
- *
- * @param ctx provides the execution context
- * @param step with current status
- *
- * @throws org.apache.commons.scxml2.model.ModelException in case there is a fatal SCXML object model problem.
- */
- void filterTransitionsSet(final SCXMLExecutionContext ctx, final Step step) throws ModelException;
-
- /**
- * Follow the candidate transitions for this execution Step, and update the
- * lists of entered and exited states accordingly.
- *
- * @param ctx provides the execution context
- * @param step The current Step
- *
- * @throws org.apache.commons.scxml2.model.ModelException in case there is a fatal SCXML object model problem.
- */
- void followTransitions(final SCXMLExecutionContext ctx, final Step step) throws ModelException;
-
- /**
- * Go over the exit list and update history information for
- * relevant states.
- *
- * @param ctx provides the execution context
- * @param step The current Step
- */
- void updateHistoryStates(final SCXMLExecutionContext ctx, final Step step);
-
- /**
- * Forward events to invoked activities, execute finalize handlers.
- *
- * @param ctx provides the execution context
- * @param event The event to be forwarded
- *
- * @throws org.apache.commons.scxml2.model.ModelException in case there is a fatal SCXML object model problem.
- */
- void processInvokes(final SCXMLExecutionContext ctx, final TriggerEvent event) throws ModelException;
-
/**
- * Initiate any new invoked activities.
- *
- * @param ctx provides the execution context
- * @param step The current Step
+ * First step in the execution of an SCXML state machine.
+ * <p>
+ * In the default implementation, this will first (re)initialize the state machine instance, destroying any existing
+ * state!
+ * </p>
+ * <p>
+ * The first step is corresponding to the Algorithm for SCXML processing from the interpret() procedure to the
+ * mainLoop() procedure up to the blocking wait for an external event.
+ * </p>
+ * <p>
+ * This step should complete the SCXML initial execution and a subsequent macroStep to stabilize the state machine
+ * again before returning.
+ * </p>
+ * <p>
+ * If the state machine no longer is running after all this, first the {@link #finalStep(SCXMLExecutionContext)}
+ * should be called for cleanup before returning.
+ * </p>
+ * @param exctx The execution context for this step
+ * @throws ModelException if the state machine instance failed to initialize or a SCXML model error occurred during
+ * the execution.
+ */
+ void firstStep(final SCXMLExecutionContext exctx) throws ModelException;
+
+ /**
+ * Next step in the execution of an SCXML state machine.
+ * <p>
+ * The next step is corresponding to the Algorithm for SCXML processing mainEventLoop() procedure after receiving an
+ * external event, up to the blocking wait for another external event.
+ * </p>
+ * <p>
+ * If the state machine isn't {@link SCXMLExecutionContext#isRunning()} (any more), this method should do nothing.
+ * </p>
+ * <p>
+ * If the provided event is a {@link TriggerEvent#CANCEL_EVENT}, the state machine should stop running.
+ * </p>
+ * <p>
+ * Otherwise, the event must be set in the {@link SCXMLSystemContext} and processing of the event then should start,
+ * and if the event leads to any transitions a microStep for this event should be performed, followed up by a
+ * macroStep to stabilize the state machine again before returning.
+ * </p>
+ * <p>
+ * If the state machine no longer is running after all this, first the {@link #finalStep(SCXMLExecutionContext)}
+ * should be called for cleanup before returning.
+ * </p>
+ * @param exctx The execution context for this step
+ * @param event The event to process
+ * @throws ModelException if a SCXML model error occurred during the execution.
+ */
+ void nextStep(final SCXMLExecutionContext exctx, final TriggerEvent event) throws ModelException;
+
+ /**
+ * The final step in the execution of an SCXML state machine.
+ * <p>
+ * This final step is corresponding to the Algorithm for SCXML processing exitInterpreter() procedure, after the
+ * state machine stopped running.
+ * </p>
+ * <p>
+ * If the state machine still is {@link SCXMLExecutionContext#isRunning()} invoking this method should simply
+ * do nothing.
+ * </p>
+ * <p>
+ * This final step should first exit all remaining active states and cancel any active invokers, before handling
+ * the possible donedata element for the last final state.
+ * </p>
+ * <p>
+ * <em>NOTE: the current implementation does not yet provide final donedata handling.</em>
+ * </p>
+ * @param exctx The execution context for this step
+ * @throws ModelException if a SCXML model error occurred during the execution.
*/
- void initiateInvokes(final SCXMLExecutor executor, final SCXMLExecutionContext ctx, final Step step);
+ void finalStep(final SCXMLExecutionContext exctx) throws ModelException;
}
-
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLSystemContext.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLSystemContext.java?rev=1584272&r1=1584271&r2=1584272&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLSystemContext.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/SCXMLSystemContext.java Thu Apr 3 07:13:42 2014
@@ -40,24 +40,23 @@ public class SCXMLSystemContext implemen
* The protected system variables names as defined in the SCXML specification
* @see <a href="http://www.w3.org/TR/scxml/#SystemVariables">http://www.w3.org/TR/scxml/#SystemVariables</a>
*/
- public static final String VARIABLE_EVENT = "_event";
- public static final String VARIABLE_SESSIONID = "_sessionid";
- public static final String VARIABLE_NAME = "_name";
- public static final String VARIABLE_IOPROCESSORS = "_ioprocessors";
- public static final String VARIABLE_X = "_x";
+ public static final String EVENT_KEY = "_event";
+ public static final String SESSIONID_KEY = "_sessionid";
+ public static final String SCXML_NAME_KEY = "_name";
+ public static final String IOPROCESSORS_KEY = "_ioprocessors";
+ public static final String X_KEY = "_x";
/**
* Commons SCXML internal system variable holding the current SCXML configuration of all (including ancestors)
* active states.
*/
- public static final String VARIABLE_ALL_STATES = "_ALL_STATES";
+ public static final String ALL_STATES_KEY = "_ALL_STATES";
/**
* The set of protected system variables names
*/
private static final Set<String> PROTECTED_NAMES = new HashSet<String>(Arrays.asList(
- new String[] { VARIABLE_EVENT, VARIABLE_SESSIONID, VARIABLE_NAME, VARIABLE_IOPROCESSORS, VARIABLE_X
- , VARIABLE_ALL_STATES }
+ new String[] {EVENT_KEY, SESSIONID_KEY, SCXML_NAME_KEY, IOPROCESSORS_KEY, X_KEY, ALL_STATES_KEY}
));
/**
@@ -67,13 +66,25 @@ public class SCXMLSystemContext implemen
private Context systemContext;
/**
+ * Initialize or replace systemContext
+ * @param systemContext the system context to set
+ */
+ void setSystemContext(Context systemContext) {
+ if (this.systemContext != null) {
+ // replace systemContext
+ systemContext.getVars().putAll(this.systemContext.getVars());
+ }
+ this.systemContext = systemContext;
+ this.protectedVars = Collections.unmodifiableMap(systemContext.getVars());
+ }
+
+ /**
* The unmodifiable wrapped variables map from the wrapped system context
*/
private Map<String, Object> protectedVars;
public SCXMLSystemContext(Context systemContext) {
- this.systemContext = systemContext;
- this.protectedVars = Collections.unmodifiableMap(systemContext.getVars());
+ setSystemContext(systemContext);
}
@Override
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/Status.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/Status.java?rev=1584272&r1=1584271&r2=1584272&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/Status.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/Status.java Thu Apr 3 07:13:42 2014
@@ -37,22 +37,17 @@ public class Status implements Serializa
/**
* The states that are currently active.
*/
- private Set<EnterableState> states;
+ private final Set<EnterableState> states = new HashSet<EnterableState>();
/**
- * Have we reached a final configuration for this state machine.
- *
- * True - if all the states are final and there are not events
- * pending from the last step. False - otherwise.
- *
- * @return Whether a final configuration has been reached.
+ * @return Whether the state machine terminated AND we reached a top level Final state.
*/
public boolean isFinal() {
return getFinalState() != null;
}
/**
- * @return Returns the single top level active final state or null otherwise
+ * @return Returns the single top level final state in which the state machine terminated, or null otherwise
*/
public Final getFinalState() {
if (states.size() == 1) {
@@ -65,13 +60,6 @@ public class Status implements Serializa
}
/**
- * Constructor.
- */
- public Status() {
- states = new HashSet<EnterableState>();
- }
-
- /**
* Get the states configuration (leaf only).
*
* @return Returns the states configuration - simple (leaf) states only.
@@ -87,8 +75,21 @@ public class Status implements Serializa
* complex ancestors up to the root.
*/
public Set<EnterableState> getAllStates() {
- return SCXMLHelper.getAncestorClosure(states, null);
+ Set<EnterableState> allStates = new HashSet<EnterableState>(states.size() * 2);
+ for (EnterableState es : states) {
+ EnterableState state = es;
+ while (state != null && allStates.add(state)) {
+ state = state.getParent();
+ }
+ }
+ return allStates;
}
+ /**
+ * Clears the status
+ */
+ public void clear() {
+ states.clear();
+ }
}
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/TriggerEvent.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/TriggerEvent.java?rev=1584272&r1=1584271&r2=1584272&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/TriggerEvent.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/TriggerEvent.java Thu Apr 3 07:13:42 2014
@@ -86,6 +86,12 @@ public class TriggerEvent implements Ser
public static final int ERROR_EVENT = 5;
/**
+ * <code>CANCEL_EVENT</code>.
+ *
+ */
+ public static final int CANCEL_EVENT = 6;
+
+ /**
* The event name.
*
*/
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/AbstractSCXMLListener.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/AbstractSCXMLListener.java?rev=1584272&r1=1584271&r2=1584272&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/AbstractSCXMLListener.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/AbstractSCXMLListener.java Thu Apr 3 07:13:42 2014
@@ -45,10 +45,10 @@ public abstract class AbstractSCXMLListe
}
/**
-* @see SCXMLListener#onTransition(TransitionTarget,TransitionTarget,Transition)
+* @see SCXMLListener#onTransition(TransitionTarget,TransitionTarget,Transition,String)
*/
public void onTransition(final TransitionTarget from,
- final TransitionTarget to, final Transition transition) {
+ final TransitionTarget to, final Transition transition, final String event) {
// empty
}
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/AbstractStateMachine.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/AbstractStateMachine.java?rev=1584272&r1=1584271&r2=1584272&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/AbstractStateMachine.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/AbstractStateMachine.java Thu Apr 3 07:13:42 2014
@@ -99,7 +99,7 @@ public abstract class AbstractStateMachi
* describes the "lifecycle" of the
* instances of this class.
*/
- public AbstractStateMachine(final URL scxmlDocument) {
+ public AbstractStateMachine(final URL scxmlDocument) throws ModelException {
// default is JEXL
this(scxmlDocument, new JexlContext(), new JexlEvaluator());
}
@@ -117,7 +117,7 @@ public abstract class AbstractStateMachi
* @see Evaluator
*/
public AbstractStateMachine(final URL scxmlDocument,
- final Context rootCtx, final Evaluator evaluator) {
+ final Context rootCtx, final Evaluator evaluator) throws ModelException {
log = LogFactory.getLog(this.getClass());
try {
stateMachine = SCXMLReader.read(scxmlDocument);
@@ -140,7 +140,7 @@ public abstract class AbstractStateMachi
*
* @since 0.7
*/
- public AbstractStateMachine(final SCXML stateMachine) {
+ public AbstractStateMachine(final SCXML stateMachine) throws ModelException {
// default is JEXL
this(stateMachine, new JexlContext(), new JexlEvaluator());
}
@@ -160,7 +160,7 @@ public abstract class AbstractStateMachi
* @since 0.7
*/
public AbstractStateMachine(final SCXML stateMachine,
- final Context rootCtx, final Evaluator evaluator) {
+ final Context rootCtx, final Evaluator evaluator) throws ModelException {
log = LogFactory.getLog(this.getClass());
initialize(stateMachine, rootCtx, evaluator);
}
@@ -173,11 +173,10 @@ public abstract class AbstractStateMachi
* @param evaluator The expression evaluator
*/
private void initialize(final SCXML stateMachine,
- final Context rootCtx, final Evaluator evaluator) {
+ final Context rootCtx, final Evaluator evaluator) throws ModelException {
engine = new SCXMLExecutor(evaluator, new SimpleDispatcher(),
new SimpleErrorReporter());
engine.setStateMachine(stateMachine);
- engine.setSuperStep(true);
engine.setRootContext(rootCtx);
engine.addListener(stateMachine, new EntryListener());
try {
@@ -308,9 +307,10 @@ public abstract class AbstractStateMachi
* @param from The "source" transition target.
* @param to The "destination" transition target.
* @param transition The transition being followed.
+ * @param event The event triggering the transition
*/
public void onTransition(final TransitionTarget from,
- final TransitionTarget to, final Transition transition) {
+ final TransitionTarget to, final Transition transition, final String event) {
// nothing to do
}
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/LogUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/LogUtils.java?rev=1584272&r1=1584271&r2=1584272&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/LogUtils.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/LogUtils.java Thu Apr 3 07:13:42 2014
@@ -34,9 +34,9 @@ public final class LogUtils {
* @return String The human readable log entry
*/
public static String transToString(final TransitionTarget from,
- final TransitionTarget to, final Transition transition) {
- StringBuffer buf = new StringBuffer("transition (");
- buf.append("event = ").append(transition.getEvent());
+ final TransitionTarget to, final Transition transition, String event) {
+ StringBuffer buf = new StringBuffer("(");
+ buf.append("event = ").append(event);
buf.append(", cond = ").append(transition.getCond());
buf.append(", from = ").append(getTTPath(from));
buf.append(", to = ").append(getTTPath(to));
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/SimpleContext.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/SimpleContext.java?rev=1584272&r1=1584271&r2=1584272&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/SimpleContext.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/SimpleContext.java Thu Apr 3 07:13:42 2014
@@ -168,7 +168,7 @@ public class SimpleContext implements Co
*/
public void setLocal(final String name, final Object value) {
getVars().put(name, value);
- if (log.isDebugEnabled() && !name.equals(SCXMLSystemContext.VARIABLE_ALL_STATES)) {
+ if (log.isDebugEnabled() && !name.equals(SCXMLSystemContext.ALL_STATES_KEY)) {
log.debug(name + " = " + String.valueOf(value));
}
}
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/SimpleErrorReporter.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/SimpleErrorReporter.java?rev=1584272&r1=1584271&r2=1584272&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/SimpleErrorReporter.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/SimpleErrorReporter.java Thu Apr 3 07:13:42 2014
@@ -24,6 +24,7 @@ import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.scxml2.ErrorReporter;
+import org.apache.commons.scxml2.model.Data;
import org.apache.commons.scxml2.model.EnterableState;
import org.apache.commons.scxml2.model.Executable;
import org.apache.commons.scxml2.model.SCXML;
@@ -105,6 +106,10 @@ public class SimpleErrorReporter impleme
TransitionTarget parent = ((Executable) errCtx).getParent();
msg.append("Expression error inside " + LogUtils.getTTPath(parent));
}
+ else if (errCtx instanceof Data) {
+ // Data expression error
+ msg.append("Expression error for data element with id "+((Data)errCtx).getId());
+ }
else if (errCtx instanceof SCXML) {
// Global Script
msg.append("Expression error inside the global script");
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/SimpleSCXMLListener.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/SimpleSCXMLListener.java?rev=1584272&r1=1584271&r2=1584272&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/SimpleSCXMLListener.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/SimpleSCXMLListener.java Thu Apr 3 07:13:42 2014
@@ -42,7 +42,7 @@ public class SimpleSCXMLListener impleme
*/
public void onEntry(final EnterableState state) {
if (log.isInfoEnabled()) {
- log.info(LogUtils.getTTPath(state));
+ log.info("enter " + LogUtils.getTTPath(state));
}
}
@@ -51,17 +51,17 @@ public class SimpleSCXMLListener impleme
*/
public void onExit(final EnterableState state) {
if (log.isInfoEnabled()) {
- log.info(LogUtils.getTTPath(state));
+ log.info("exit " + LogUtils.getTTPath(state));
}
}
/**
-* @see SCXMLListener#onTransition(TransitionTarget,TransitionTarget,Transition)
+* @see SCXMLListener#onTransition(TransitionTarget,TransitionTarget,Transition,String)
*/
public void onTransition(final TransitionTarget from,
- final TransitionTarget to, final Transition transition) {
+ final TransitionTarget to, final Transition transition, String event) {
if (log.isInfoEnabled()) {
- log.info(LogUtils.transToString(from, to, transition));
+ log.info("transition " + LogUtils.transToString(from, to, transition, event));
}
}
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/SimpleScheduler.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/SimpleScheduler.java?rev=1584272&r1=1584271&r2=1584272&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/SimpleScheduler.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/SimpleScheduler.java Thu Apr 3 07:13:42 2014
@@ -28,7 +28,6 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.scxml2.EventDispatcher;
import org.apache.commons.scxml2.SCXMLExecutor;
-import org.apache.commons.scxml2.SCXMLHelper;
import org.apache.commons.scxml2.TriggerEvent;
import org.apache.commons.scxml2.model.ModelException;
import org.w3c.dom.Node;
@@ -120,10 +119,9 @@ public class SimpleScheduler implements
}
// We only handle the "scxml" type (which is the default too)
- if (SCXMLHelper.isStringEmpty(type)
- || type.trim().equalsIgnoreCase(TYPE_SCXML)) {
+ if (type == null || type.equalsIgnoreCase(TYPE_SCXML)) {
- if (!SCXMLHelper.isStringEmpty(target)) {
+ if (target != null) {
// We know of no other target
if (log.isWarnEnabled()) {
log.warn("<send>: Unavailable target - " + target);
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/Tracer.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/Tracer.java?rev=1584272&r1=1584271&r2=1584272&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/Tracer.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/Tracer.java Thu Apr 3 07:13:42 2014
@@ -107,11 +107,11 @@ public class Tracer implements ErrorHand
}
/**
- * @see SCXMLListener#onTransition(TransitionTarget,TransitionTarget,Transition)
+ * @see SCXMLListener#onTransition(TransitionTarget,TransitionTarget,Transition,String)
*/
public void onTransition(final TransitionTarget from,
- final TransitionTarget to, final Transition transition) {
- scxmlListener.onTransition(from, to, transition);
+ final TransitionTarget to, final Transition transition, final String event) {
+ scxmlListener.onTransition(from, to, transition, event);
}
/**
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/GroovySCXMLScript.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/GroovySCXMLScript.java?rev=1584272&r1=1584271&r2=1584272&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/GroovySCXMLScript.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/groovy/GroovySCXMLScript.java Thu Apr 3 07:13:42 2014
@@ -22,6 +22,7 @@ import java.util.Map;
import java.util.Set;
import org.apache.commons.scxml2.Builtin;
+import org.apache.commons.scxml2.Context;
import org.apache.commons.scxml2.SCXMLSystemContext;
import org.apache.commons.scxml2.model.EnterableState;
@@ -55,7 +56,7 @@ public abstract class GroovySCXMLScript
*/
@SuppressWarnings("unchecked")
private Map<String, String> getNamespaces() {
- return (Map<String, String>) context.get("_ALL_NAMESPACES");
+ return (Map<String, String>) context.get(Context.NAMESPACES_KEY);
}
/**
@@ -64,7 +65,7 @@ public abstract class GroovySCXMLScript
*/
@SuppressWarnings("unchecked")
private Set<EnterableState> getAllStates() {
- return (Set<EnterableState>) context.get(SCXMLSystemContext.VARIABLE_ALL_STATES);
+ return (Set<EnterableState>) context.get(SCXMLSystemContext.ALL_STATES_KEY);
}
/**
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/javascript/JSEvaluator.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/javascript/JSEvaluator.java?rev=1584272&r1=1584271&r2=1584272&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/javascript/JSEvaluator.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/javascript/JSEvaluator.java Thu Apr 3 07:13:42 2014
@@ -28,6 +28,7 @@ import org.apache.commons.scxml2.Builtin
import org.apache.commons.scxml2.Context;
import org.apache.commons.scxml2.Evaluator;
import org.apache.commons.scxml2.SCXMLExpressionException;
+import org.apache.commons.scxml2.SCXMLSystemContext;
import org.w3c.dom.Node;
/**
@@ -101,8 +102,8 @@ public class JSEvaluator implements Eval
Bindings bindings = engine.getBindings (ScriptContext.ENGINE_SCOPE);
// ... replace built-in functions
- String jsExpression = IN_FN.matcher(expression).replaceAll("_builtin.isMember(_ALL_STATES, ");
- jsExpression = DATA_FN.matcher(jsExpression).replaceAll("_builtin.data(_ALL_NAMESPACES, ");
+ String jsExpression = IN_FN.matcher(expression).replaceAll("_builtin.isMember("+SCXMLSystemContext.ALL_STATES_KEY +", ");
+ jsExpression = DATA_FN.matcher(jsExpression).replaceAll("_builtin.data("+Context.NAMESPACES_KEY+", ");
// ... evaluate
return engine.eval(jsExpression,new JSBindings(context,bindings));
@@ -161,8 +162,8 @@ public class JSEvaluator implements Eval
// ... replace built-in functions
String jsExpression = IN_FN.matcher(expression).replaceAll("_builtin.isMember(_ALL_STATES, ");
- jsExpression = DATA_FN.matcher(jsExpression).replaceFirst("_builtin.dataNode(_ALL_NAMESPACES, ");
- jsExpression = DATA_FN.matcher(jsExpression).replaceAll("_builtin.data(_ALL_NAMESPACES, ");
+ jsExpression = DATA_FN.matcher(jsExpression).replaceFirst("_builtin.dataNode("+Context.NAMESPACES_KEY+", ");
+ jsExpression = DATA_FN.matcher(jsExpression).replaceAll("_builtin.data("+Context.NAMESPACES_KEY+", ");
// ... evaluate
return (Node) engine.eval(jsExpression,new JSBindings(context,bindings));
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/jexl/JexlBuiltin.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/jexl/JexlBuiltin.java?rev=1584272&r1=1584271&r2=1584272&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/jexl/JexlBuiltin.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/jexl/JexlBuiltin.java Thu Apr 3 07:13:42 2014
@@ -20,6 +20,7 @@ import java.util.Map;
import java.util.Set;
import org.apache.commons.scxml2.Builtin;
+import org.apache.commons.scxml2.Context;
import org.apache.commons.scxml2.SCXMLSystemContext;
import org.apache.commons.scxml2.model.EnterableState;
@@ -47,7 +48,7 @@ public final class JexlBuiltin {
*/
@SuppressWarnings("unchecked")
private Map<String, String> getNamespaces() {
- return (Map<String, String>) context.get("_ALL_NAMESPACES");
+ return (Map<String, String>) context.get(Context.NAMESPACES_KEY);
}
/**
@@ -56,7 +57,7 @@ public final class JexlBuiltin {
*/
@SuppressWarnings("unchecked")
private Set<EnterableState> getAllStates() {
- return (Set<EnterableState>) context.get(SCXMLSystemContext.VARIABLE_ALL_STATES);
+ return (Set<EnterableState>) context.get(SCXMLSystemContext.ALL_STATES_KEY);
}
/**
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/xpath/FunctionResolver.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/xpath/FunctionResolver.java?rev=1584272&r1=1584271&r2=1584272&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/xpath/FunctionResolver.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/xpath/FunctionResolver.java Thu Apr 3 07:13:42 2014
@@ -45,9 +45,7 @@ public class FunctionResolver implements
private static final String NAMESPACE_COMMONS_SCXML =
"http://commons.apache.org/scxml";
/** The {@link Context} key to retrieve all the current states. */
- private static final String STATES = SCXMLSystemContext.VARIABLE_ALL_STATES;
- /** The {@link Context} key to retrieve all the current namespaces. */
- private static final String NAMESPACES = "_ALL_NAMESPACES";
+ private static final String STATES = SCXMLSystemContext.ALL_STATES_KEY;
/** Functions map. */
private final Map<FunctionKey, XPathFunction> functions =
@@ -138,7 +136,7 @@ public class FunctionResolver implements
@SuppressWarnings("unchecked")
public Object evaluate(final List args) throws XPathFunctionException {
Map<String, String> namespaces =
- (Map<String, String>) xctx.get(NAMESPACES);
+ (Map<String, String>) xctx.get(Context.NAMESPACES_KEY);
Object node = xctx.get((String) args.get(0));
return Builtin.data(namespaces, node, (String) args.get(1));
}
@@ -163,7 +161,7 @@ public class FunctionResolver implements
@SuppressWarnings("unchecked")
public Object evaluate(final List args) throws XPathFunctionException {
Map<String, String> namespaces =
- (Map<String, String>) xctx.get(NAMESPACES);
+ (Map<String, String>) xctx.get(Context.NAMESPACES_KEY);
Object node = xctx.get((String) args.get(0));
return Builtin.dataNode(namespaces, node, (String) args.get(1));
}
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/xpath/XPathEvaluator.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/xpath/XPathEvaluator.java?rev=1584272&r1=1584271&r2=1584272&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/xpath/XPathEvaluator.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/env/xpath/XPathEvaluator.java Thu Apr 3 07:13:42 2014
@@ -152,7 +152,7 @@ public class XPathEvaluator implements E
fnResolver.setContext(xctx);
XPath xpath = factory.newXPath();
NamespaceContext nsCtx =
- new ExpressionNSContext((Map<String, String>) ctx.get("_ALL_NAMESPACES"));
+ new ExpressionNSContext((Map<String, String>) ctx.get(Context.NAMESPACES_KEY));
xpath.setNamespaceContext(nsCtx);
return xpath;
}
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/invoke/AsyncTrigger.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/invoke/AsyncTrigger.java?rev=1584272&r1=1584271&r2=1584272&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/invoke/AsyncTrigger.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/invoke/AsyncTrigger.java Thu Apr 3 07:13:42 2014
@@ -16,7 +16,7 @@
*/
package org.apache.commons.scxml2.invoke;
-import org.apache.commons.scxml2.SCXMLExecutor;
+import org.apache.commons.scxml2.SCXMLIOProcessor;
import org.apache.commons.scxml2.TriggerEvent;
/**
@@ -25,19 +25,19 @@ import org.apache.commons.scxml2.Trigger
*/
class AsyncTrigger implements Runnable {
- /** The state machine executor. */
- private final SCXMLExecutor executor;
+ /** 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 executor The {@link SCXMLExecutor} to trigger the event on.
+ * @param ioProcessor The {@link org.apache.commons.scxml2.SCXMLIOProcessor} to trigger the event on.
* @param event The {@link TriggerEvent}.
*/
- AsyncTrigger(final SCXMLExecutor executor, final TriggerEvent event) {
- this.executor = executor;
+ AsyncTrigger(final SCXMLIOProcessor ioProcessor, final TriggerEvent event) {
+ this.ioProcessor = ioProcessor;
this.event = event;
}
@@ -52,7 +52,7 @@ class AsyncTrigger implements Runnable {
* Fire the event(s).
*/
public void run() {
- executor.addEvent(event);
+ ioProcessor.addEvent(event);
}
}
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/invoke/Invoker.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/invoke/Invoker.java?rev=1584272&r1=1584271&r2=1584272&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/invoke/Invoker.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/invoke/Invoker.java Thu Apr 3 07:13:42 2014
@@ -18,7 +18,8 @@ package org.apache.commons.scxml2.invoke
import java.util.Map;
-import org.apache.commons.scxml2.SCXMLExecutor;
+import org.apache.commons.scxml2.Evaluator;
+import org.apache.commons.scxml2.SCXMLIOProcessor;
import org.apache.commons.scxml2.TriggerEvent;
/**
@@ -28,10 +29,10 @@ import org.apache.commons.scxml2.Trigger
*
* <p>Invocable activities must first register an Invoker implementation class
* for the appropriate "target" (attribute of <invoke>) with the
- * parent <code>SCXMLExecutor</code>.</p>
+ * parent <code>SCXMLParentIOProcessor</code>.</p>
*
* <p>The communication link between the parent state machine executor and
- * the invoked activity is a bi-directional events pipe.</p>
+ * the invoked activity is a asynchronous bi-directional events pipe.</p>
*
* <p>All events triggered on the parent state machine get forwarded to the
* invoked activity. The processing semantics for these events depend
@@ -42,16 +43,15 @@ import org.apache.commons.scxml2.Trigger
* when it concludes. It may fire additional events before the "done"
* event. The semantics of any additional events depend upon the
* "target". The invoked activity must not fire any events after the "done"
- * event. The name of the special "done" event must be the ID of the parent
- * state wherein the corresponding <invoke> resides, with the String
- * ".invoke.done" appended.</p>
+ * event. The name of the special "done" event must be "done.invoke.id" with
+ * the ID of the parent state wherein the corresponding <invoke> resides,</p>
*
* <p>The Invoker "lifecycle" is outlined below:
* <ol>
* <li>Instantiation via {@link Class#newInstance()}
* (Invoker implementation requires accessible constructor).</li>
- * <li>Configuration (setters for parent state ID and
- * {@link SCXMLExecutor}).</li>
+ * <li>Configuration (setters for invoke ID and
+ * {@link org.apache.commons.scxml2.SCXMLIOProcessor}).</li>
* <li>Initiation of invoked activity via invoke() method, passing
* the source URI and the map of params.</li>
* <li>Zero or more bi-directional event triggering.</li>
@@ -61,29 +61,35 @@ import org.apache.commons.scxml2.Trigger
*
* <p><b>Note:</b> The semantics of <invoke> are necessarily
* asynchronous, tending towards long(er) running interactions with external
- * processes. Implementations must not communicate with the parent state
+ * processes. Implementations cannot communicate with the parent state
* machine executor in a synchronous manner. For synchronous
* communication semantics, use <event> or custom actions instead.</p>
*/
public interface Invoker {
/**
- * Set the state ID of the owning state for the <invoke>.
+ * Set the invoke ID provided by the parent state machine executor
* Implementations must use this ID for constructing the event name for
* the special "done" event (and optionally, for other event names
* as well).
*
- * @param parentStateId The ID of the parent state.
+ * @param invokeId The invoke ID provided by the parent state machine executor.
*/
- void setParentStateId(String parentStateId);
+ void setInvokeId(String invokeId);
/**
- * Set the execution "context" of the parent state machine, which provides the
+ * Set I/O Processor of the parent state machine, which provides the
* channel.
*
- * @param parentExecutor The execution "context" of the parent state machine.
+ * @param parentIOProcessor The I/O Processor of the parent state machine.
*/
- void setParentExecutor(SCXMLExecutor parentExecutor);
+ void setParentIOProcessor(SCXMLIOProcessor parentIOProcessor);
+
+ /**
+ * Set the Evaluator to be used by the child state machine (to ensure/enforce a compatible data model)
+ * @param evaluator the Evaluator to be used
+ */
+ void setEvaluator(Evaluator evaluator);
/**
* Begin this invocation.
@@ -97,18 +103,18 @@ public interface Invoker {
throws InvokerException;
/**
- * Forwards the events triggered on the parent state machine
+ * Forwards the event triggered on the parent state machine
* on to the invoked activity.
*
- * @param evts
- * an array of external events which triggered during the last
+ * @param event
+ * an external event which triggered during the last
* time quantum
*
* @throws InvokerException In case there is a fatal problem with
* processing the events forwarded by the
* parent state machine.
*/
- void parentEvents(TriggerEvent[] evts)
+ void parentEvent(TriggerEvent event)
throws InvokerException;
/**
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/invoke/SimpleSCXMLInvoker.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/invoke/SimpleSCXMLInvoker.java?rev=1584272&r1=1584271&r2=1584272&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/invoke/SimpleSCXMLInvoker.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/invoke/SimpleSCXMLInvoker.java Thu Apr 3 07:13:42 2014
@@ -26,6 +26,7 @@ import javax.xml.stream.XMLStreamExcepti
import org.apache.commons.scxml2.Context;
import org.apache.commons.scxml2.Evaluator;
import org.apache.commons.scxml2.SCXMLExecutor;
+import org.apache.commons.scxml2.SCXMLIOProcessor;
import org.apache.commons.scxml2.TriggerEvent;
import org.apache.commons.scxml2.env.SimpleDispatcher;
import org.apache.commons.scxml2.env.SimpleErrorReporter;
@@ -44,38 +45,35 @@ public class SimpleSCXMLInvoker implemen
private static final long serialVersionUID = 1L;
/** Parent state ID. */
private String parentStateId;
- /** Event prefix, all events sent to the parent executor must begin
- * with this prefix. */
- private String eventPrefix;
- /** Invoking document's SCXMLExecutor */
- private SCXMLExecutor parentExecutor;
+ /** Invoking document's external I/O Processor */
+ private SCXMLIOProcessor parentIOProcessor;
+ /** The Evaluator provided by the parent executor */
+ private Evaluator evaluator;
/** The invoked state machine executor. */
private SCXMLExecutor executor;
/** Cancellation status. */
private boolean cancelled;
- //// Constants
- /** Prefix for all events sent to the parent state machine. */
- private static String invokePrefix = ".invoke.";
- /** Suffix for invoke done event. */
- private static String invokeDone = "done";
- /** Suffix for invoke cancel response event. */
- private static String invokeCancelResponse = "cancel.response";
-
/**
* {@inheritDoc}.
*/
- public void setParentStateId(final String parentStateId) {
- this.parentStateId = parentStateId;
- this.eventPrefix = this.parentStateId + invokePrefix;
+ public void setInvokeId(final String invokeId) {
+ this.parentStateId = invokeId;
this.cancelled = false;
}
/**
* {@inheritDoc}.
*/
- public void setParentExecutor(final SCXMLExecutor parentExecutor) {
- this.parentExecutor = parentExecutor;
+ public void setParentIOProcessor(SCXMLIOProcessor parentIOProcessor) {
+ this.parentIOProcessor = parentIOProcessor;
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ public void setEvaluator(final Evaluator evaluator) {
+ this.evaluator = evaluator;
}
/**
@@ -83,7 +81,7 @@ public class SimpleSCXMLInvoker implemen
*/
public void invoke(final String source, final Map<String, Object> params)
throws InvokerException {
- SCXML scxml = null;
+ SCXML scxml;
try {
scxml = SCXMLReader.read(new URL(source));
} catch (ModelException me) {
@@ -93,15 +91,18 @@ public class SimpleSCXMLInvoker implemen
} catch (XMLStreamException xse) {
throw new InvokerException(xse.getMessage(), xse.getCause());
}
- Evaluator eval = parentExecutor.getEvaluator();
- executor = new SCXMLExecutor(eval,
- new SimpleDispatcher(), new SimpleErrorReporter());
- Context rootCtx = eval.newContext(null);
+ executor = new SCXMLExecutor(evaluator, new SimpleDispatcher(), new SimpleErrorReporter());
+ Context rootCtx = evaluator.newContext(null);
for (Map.Entry<String, Object> entry : params.entrySet()) {
rootCtx.setLocal(entry.getKey(), entry.getValue());
}
executor.setRootContext(rootCtx);
- executor.setStateMachine(scxml);
+ try {
+ executor.setStateMachine(scxml);
+ }
+ catch (ModelException me) {
+ throw new InvokerException(me);
+ }
executor.addListener(scxml, new SimpleSCXMLListener());
executor.registerInvokerClass("scxml", this.getClass());
try {
@@ -110,30 +111,28 @@ public class SimpleSCXMLInvoker implemen
throw new InvokerException(me.getMessage(), me.getCause());
}
if (executor.getCurrentStatus().isFinal()) {
- TriggerEvent te = new TriggerEvent(eventPrefix + invokeDone,
- TriggerEvent.SIGNAL_EVENT);
- new AsyncTrigger(parentExecutor, te).start();
+ TriggerEvent te = new TriggerEvent("done.invoke."+parentStateId, TriggerEvent.SIGNAL_EVENT);
+ new AsyncTrigger(parentIOProcessor, te).start();
}
}
/**
* {@inheritDoc}.
*/
- public void parentEvents(final TriggerEvent[] evts)
+ public void parentEvent(final TriggerEvent evt)
throws InvokerException {
if (cancelled) {
return; // no further processing should take place
}
boolean doneBefore = executor.getCurrentStatus().isFinal();
try {
- executor.triggerEvents(evts);
+ executor.triggerEvent(evt);
} catch (ModelException me) {
throw new InvokerException(me.getMessage(), me.getCause());
}
if (!doneBefore && executor.getCurrentStatus().isFinal()) {
- TriggerEvent te = new TriggerEvent(eventPrefix + invokeDone,
- TriggerEvent.SIGNAL_EVENT);
- new AsyncTrigger(parentExecutor, te).start();
+ TriggerEvent te = new TriggerEvent("done.invoke."+parentStateId,TriggerEvent.SIGNAL_EVENT);
+ new AsyncTrigger(parentIOProcessor, te).start();
}
}
@@ -143,9 +142,11 @@ public class SimpleSCXMLInvoker implemen
public void cancel()
throws InvokerException {
cancelled = true;
- TriggerEvent te = new TriggerEvent(eventPrefix
- + invokeCancelResponse, TriggerEvent.SIGNAL_EVENT);
- new AsyncTrigger(parentExecutor, te).start();
+ try {
+ executor.triggerEvent(new TriggerEvent("cancel.invoke."+parentStateId, TriggerEvent.CANCEL_EVENT));
+ } catch (ModelException me) {
+ throw new InvokerException(me.getMessage(), me.getCause());
+ }
}
}
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/ModelUpdater.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/ModelUpdater.java?rev=1584272&r1=1584271&r2=1584272&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/ModelUpdater.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/ModelUpdater.java Thu Apr 3 07:13:42 2014
@@ -24,7 +24,6 @@ import java.util.Set;
import java.util.StringTokenizer;
import org.apache.commons.logging.LogFactory;
-import org.apache.commons.scxml2.SCXMLHelper;
import org.apache.commons.scxml2.model.EnterableState;
import org.apache.commons.scxml2.model.History;
import org.apache.commons.scxml2.model.Initial;
@@ -170,7 +169,6 @@ final class ModelUpdater {
// If 'initial' is not specified, the default initial state is
// the first child state in document order.
initialTransition.getTargets().add(scxml.getFirstChild());
- initialTransition.getPaths(); // init paths
}
scxml.setInitialTransition(initialTransition);
@@ -261,7 +259,7 @@ final class ModelUpdater {
}
SimpleTransition initialTransition = ini.getTransition();
updateTransition(initialTransition, targets);
- List<TransitionTarget> initialStates = initialTransition.getTargets();
+ Set<TransitionTarget> initialStates = initialTransition.getTargets();
// we have to allow for an indirect descendant initial (targets)
//check that initialState is a descendant of s
if (initialStates.size() == 0) {
@@ -269,7 +267,7 @@ final class ModelUpdater {
new Object[] {getName(state)});
} else {
for (TransitionTarget initialState : initialStates) {
- if (!SCXMLHelper.isDescendant(initialState, state)) {
+ if (!initialState.isDescendantOf(state)) {
logAndThrowModelError(ERR_STATE_BAD_INIT,
new Object[] {getName(state)});
}
@@ -293,22 +291,14 @@ final class ModelUpdater {
}
for (Invoke inv : state.getInvokes()) {
- String type = inv.getType();
- if (SCXMLHelper.isStringEmpty(type)) {
- logAndThrowModelError(ERR_INVOKE_NO_TYPE,
- new Object[] {getName(state)});
+ if (inv.getType() == null) {
+ logAndThrowModelError(ERR_INVOKE_NO_TYPE, new Object[] {getName(state)});
}
- String src = inv.getSrc();
- boolean noSrc = SCXMLHelper.isStringEmpty(src);
- String srcexpr = inv.getSrcexpr();
- boolean noSrcexpr = SCXMLHelper.isStringEmpty(srcexpr);
- if (noSrc && noSrcexpr) {
- logAndThrowModelError(ERR_INVOKE_NO_SRC,
- new Object[] {getName(state)});
+ if (inv.getSrc() == null && inv.getSrcexpr() == null) {
+ logAndThrowModelError(ERR_INVOKE_NO_SRC, new Object[] {getName(state)});
}
- if (!noSrc && !noSrcexpr) {
- logAndThrowModelError(ERR_INVOKE_AMBIGUOUS_SRC,
- new Object[] {getName(state)});
+ if (inv.getSrc() != null && inv.getSrcexpr() != null) {
+ logAndThrowModelError(ERR_INVOKE_AMBIGUOUS_SRC, new Object[] {getName(state)});
}
}
@@ -366,7 +356,7 @@ final class ModelUpdater {
}
else {
updateTransition(transition, targets);
- List<TransitionTarget> historyStates = transition.getTargets();
+ Set<TransitionTarget> historyStates = transition.getTargets();
if (historyStates.size() == 0) {
logAndThrowModelError(ERR_STATE_NO_HIST,
new Object[] {getName(parent)});
@@ -380,7 +370,7 @@ final class ModelUpdater {
}
} else {
// Deep history
- if (!SCXMLHelper.isDescendant(historyState, parent)) {
+ if (!historyState.isDescendantOf(parent)) {
logAndThrowModelError(ERR_STATE_BAD_DEEP_HIST,
new Object[] {getName(parent)});
}
@@ -402,8 +392,8 @@ final class ModelUpdater {
if (next == null) { // stay transition
return;
}
- List<TransitionTarget> tts = transition.getTargets();
- if (tts.size() == 0) {
+ Set<TransitionTarget> tts = transition.getTargets();
+ if (tts.isEmpty()) {
// 'next' is a space separated list of transition target IDs
StringTokenizer ids = new StringTokenizer(next);
while (ids.hasMoreTokens()) {
@@ -423,7 +413,6 @@ final class ModelUpdater {
}
}
}
- transition.getPaths(); // init paths
}
/**
@@ -455,16 +444,16 @@ final class ModelUpdater {
String name = "anonymous transition target";
if (tt instanceof State) {
name = "anonymous state";
- if (!SCXMLHelper.isStringEmpty(tt.getId())) {
+ if (tt.getId() != null) {
name = "state with ID \"" + tt.getId() + "\"";
}
} else if (tt instanceof Parallel) {
name = "anonymous parallel";
- if (!SCXMLHelper.isStringEmpty(tt.getId())) {
+ if (tt.getId() != null) {
name = "parallel with ID \"" + tt.getId() + "\"";
}
} else {
- if (!SCXMLHelper.isStringEmpty(tt.getId())) {
+ if (tt.getId() != null) {
name = "transition target with ID \"" + tt.getId() + "\"";
}
}
@@ -473,37 +462,45 @@ final class ModelUpdater {
/**
* If a transition has multiple targets, then they satisfy the following
- * criteria.
+ * criteria:
* <ul>
- * <li>They must belong to the regions of the same parallel</li>
- * <li>All regions must be represented with exactly one target</li>
+ * <li>No target is an ancestor of any other target on the list</li>
+ * <li>A full legal state configuration results when all ancestors and default initial descendants have been added.
+ * <br/>This means that they all must share the same least common parallel ancestor.
+ * </li>
* </ul>
*
* @param tts The transition targets
* @return Whether this is a legal configuration
+ * @see <a href=http://www.w3.org/TR/2014/CR-scxml-20140313/#LegalStateConfigurations">
+ * http://www.w3.org/TR/2014/CR-scxml-20140313/#LegalStateConfigurations</a>
*/
- private static boolean verifyTransitionTargets(final List<TransitionTarget> tts) {
+ private static boolean verifyTransitionTargets(final Set<TransitionTarget> tts) {
if (tts.size() <= 1) { // No contention
return true;
}
- TransitionTarget lca = SCXMLHelper.getLCA(tts.get(0), tts.get(1));
- if (lca == null || !(lca instanceof Parallel)) {
- return false; // Must have a Parallel LCA
- }
- Parallel parallel = (Parallel) lca;
- Set<TransitionTarget> regions = new HashSet<TransitionTarget>();
+
+ Set<EnterableState> parents = new HashSet<EnterableState>();
for (TransitionTarget tt : tts) {
- while (tt != null && tt.getParent() != parallel) {
- tt = tt.getParent();
+ boolean hasParallelParent = false;
+ for (int i = tt.getNumberOfAncestors()-1; i > -1; i--) {
+ EnterableState parent = tt.getAncestor(i);
+ if (parent instanceof Parallel) {
+ hasParallelParent = true;
+ // keep on 'reading' as a parallel may have a parent parallel (and even intermediate states)
+ }
+ else {
+ if (!parents.add(parent)) {
+ // this TransitionTarget is an descendant of another, or shares the same Parallel region
+ return false;
+ }
+ }
}
- if (tt == null) {
- // target outside lca
+ if (!hasParallelParent || !(tt.getAncestor(0) instanceof Parallel)) {
+ // multiple targets MUST all be children of a shared parallel
return false;
}
- if (!regions.add(tt)) {
- return false; // One per region
- }
}
- return regions.size() == parallel.getChildren().size();
- }
+ return true;
+ }
}
\ No newline at end of file
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java?rev=1584272&r1=1584271&r2=1584272&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLReader.java Thu Apr 3 07:13:42 2014
@@ -48,7 +48,6 @@ import javax.xml.validation.Validator;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.scxml2.PathResolver;
-import org.apache.commons.scxml2.SCXMLHelper;
import org.apache.commons.scxml2.env.SimpleErrorHandler;
import org.apache.commons.scxml2.env.URLResolver;
import org.apache.commons.scxml2.model.Action;
@@ -208,6 +207,15 @@ public final class SCXMLReader {
+" required attribute \"{1}\" value at {2}";
/**
+ * Error message when the target of the URI fragment in a <state>'s
+ * "src" attribute is not a <state> or <final> in
+ * the referenced document.
+ */
+ private static final String ERR_ATTRIBUTE_NOT_BOOLEAN = "Illegal value \"{0}\""
+ + "for attribute \"{1}\" in element <{2}> at {3}."
+ +" Only the value \"true\" or \"false\" is allowed.";
+
+ /**
* Error message when the element (state|parallel|final|history) uses an id value
* with the reserved prefix {@link SCXML#GENERATED_TT_ID_PREFIX}.
*/
@@ -260,6 +268,7 @@ public final class SCXMLReader {
//---- ATTRIBUTE NAMES ----//
private static final String ATTR_ARRAY = "array";
+ private static final String ATTR_AUTOFORWARD = "autoforward";
private static final String ATTR_COND = "cond";
private static final String ATTR_DELAY = "delay";
private static final String ATTR_EVENT = "event";
@@ -813,6 +822,8 @@ public final class SCXMLReader {
parallel.addTransition(readTransition(reader, configuration));
} else if (ELEM_STATE.equals(name)) {
readState(reader, configuration, scxml, parallel);
+ } else if (ELEM_PARALLEL.equals(name)) {
+ readParallel(reader, configuration, scxml, parallel);
} else if (ELEM_ONENTRY.equals(name)) {
readOnEntry(reader, configuration, parallel);
} else if (ELEM_ONEXIT.equals(name)) {
@@ -971,8 +982,12 @@ public final class SCXMLReader {
if (source instanceof State && ts instanceof State) {
State s = (State) ts;
State include = (State) source;
- s.setOnEntry(include.getOnEntry());
- s.setOnExit(include.getOnExit());
+ for (OnEntry onentry : include.getOnEntries()) {
+ s.addOnEntry(onentry);
+ }
+ for (OnExit onexit : include.getOnExits()) {
+ s.addOnExit(onexit);
+ }
s.setDatamodel(include.getDatamodel());
List<History> histories = include.getHistory();
for (History h : histories) {
@@ -1117,6 +1132,7 @@ public final class SCXMLReader {
invoke.setSrc(readAV(reader, ATTR_SRC));
invoke.setSrcexpr(readAV(reader, ATTR_SRCEXPR));
invoke.setType(readAV(reader, ATTR_TYPE));
+ invoke.setAutoForward(readBooleanAV(reader, ELEM_INVOKE, ATTR_AUTOFORWARD));
invoke.setPathResolver(configuration.pathResolver);
readNamespaces(configuration, invoke);
@@ -1333,8 +1349,9 @@ public final class SCXMLReader {
throws XMLStreamException, ModelException {
OnEntry onentry = new OnEntry();
+ onentry.setRaiseEvent(readBooleanAV(reader, ELEM_ONENTRY, ATTR_EVENT));
readExecutableContext(reader, configuration, onentry, null);
- es.setOnEntry(onentry);
+ es.addOnEntry(onentry);
}
/**
@@ -1353,8 +1370,9 @@ public final class SCXMLReader {
throws XMLStreamException, ModelException {
OnExit onexit = new OnExit();
+ onexit.setRaiseEvent(readBooleanAV(reader, ELEM_ONEXIT, ATTR_EVENT));
readExecutableContext(reader, configuration, onexit, null);
- es.setOnExit(onexit);
+ es.addOnExit(onexit);
}
/**
@@ -2107,6 +2125,14 @@ public final class SCXMLReader {
}
/**
+ * @param input input string to check if null or empty after trim
+ * @return null if input is null or empty after trim()
+ */
+ private static String nullIfEmpty(String input) {
+ return input == null || input.trim().length()==0 ? null : input.trim();
+ }
+
+ /**
* Get the attribute value at the current reader location.
*
* @param reader The {@link XMLStreamReader} providing the SCXML document to parse.
@@ -2115,7 +2141,30 @@ public final class SCXMLReader {
* @return The value of the attribute.
*/
private static String readAV(final XMLStreamReader reader, final String attrLocalName) {
- return reader.getAttributeValue(XMLNS_DEFAULT, attrLocalName);
+ return nullIfEmpty(reader.getAttributeValue(XMLNS_DEFAULT, attrLocalName));
+ }
+
+ /**
+ * Get the Boolean attribute value at the current reader location.
+ *
+ * @param reader The {@link XMLStreamReader} providing the SCXML document to parse.
+ * @param elementName The name of the element for which the attribute value is needed.
+ * @param attrLocalName The attribute name whose value is needed.
+ *
+ * @return The Boolean value of the attribute.
+ * @throws ModelException When the attribute value is not empty but neither "true" or "false".
+ */
+ private static Boolean readBooleanAV(final XMLStreamReader reader, final String elementName,
+ final String attrLocalName)
+ throws ModelException {
+ String value = nullIfEmpty(reader.getAttributeValue(XMLNS_DEFAULT, attrLocalName));
+ Boolean result = "true".equals(value) ? Boolean.TRUE : "false".equals(value) ? Boolean.FALSE : null;
+ if (result == null && value != null) {
+ MessageFormat msgFormat = new MessageFormat(ERR_ATTRIBUTE_NOT_BOOLEAN);
+ String errMsg = msgFormat.format(new Object[] {value, attrLocalName, elementName, reader.getLocation()});
+ throw new ModelException(errMsg);
+ }
+ return result;
}
/**
@@ -2130,8 +2179,8 @@ public final class SCXMLReader {
*/
private static String readRequiredAV(final XMLStreamReader reader, final String elementName, final String attrLocalName)
throws ModelException {
- String value = reader.getAttributeValue(XMLNS_DEFAULT, attrLocalName);
- if (SCXMLHelper.isStringEmpty(value)) {
+ String value = nullIfEmpty(reader.getAttributeValue(XMLNS_DEFAULT, attrLocalName));
+ if (value == null) {
MessageFormat msgFormat = new MessageFormat(ERR_REQUIRED_ATTRIBUTE_MISSING);
String errMsg = msgFormat.format(new Object[] {elementName, attrLocalName, reader.getLocation()});
throw new ModelException(errMsg);
@@ -2143,7 +2192,7 @@ public final class SCXMLReader {
final String elementName)
throws ModelException {
String id = readAV(reader, ATTR_ID);
- if (SCXMLHelper.isStringEmpty(id)) {
+ if (id == null) {
id = scxml.generateTransitionTargetId();
}
else if (id.startsWith(SCXML.GENERATED_TT_ID_PREFIX)) {
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLWriter.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLWriter.java?rev=1584272&r1=1584271&r2=1584272&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLWriter.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/io/SCXMLWriter.java Thu Apr 3 07:13:42 2014
@@ -42,7 +42,6 @@ import javax.xml.transform.stream.Stream
import javax.xml.transform.stream.StreamSource;
import org.apache.commons.logging.LogFactory;
-import org.apache.commons.scxml2.SCXMLHelper;
import org.apache.commons.scxml2.model.Action;
import org.apache.commons.scxml2.model.Assign;
import org.apache.commons.scxml2.model.Cancel;
@@ -156,6 +155,7 @@ public class SCXMLWriter {
//---- ATTRIBUTE NAMES ----//
private static final String ATTR_ARRAY = "array";
+ private static final String ATTR_AUTOFORWARD = "autoforward";
private static final String ATTR_COND = "cond";
private static final String ATTR_DELAY = "delay";
private static final String ATTR_EVENT = "event";
@@ -347,6 +347,59 @@ public class SCXMLWriter {
}
//---------------------- PRIVATE UTILITY METHODS ----------------------//
+
+ /**
+ * Escape XML strings for serialization.
+ * The basic algorithm is taken from Commons Lang (see oacl.Entities.java)
+ *
+ * @param str A string to be escaped
+ * @return The escaped string
+ */
+ private static String escapeXML(final String str) {
+ if (str == null) {
+ return null;
+ }
+
+ // Make the writer an arbitrary bit larger than the source string
+ int len = str.length();
+ StringWriter stringWriter = new StringWriter(len + 8);
+
+ for (int i = 0; i < len; i++) {
+ char c = str.charAt(i);
+ String entityName = null; // Look for XML 1.0 predefined entities
+ switch (c) {
+ case '"':
+ entityName = "quot";
+ break;
+ case '&':
+ entityName = "amp";
+ break;
+ case '<':
+ entityName = "lt";
+ break;
+ case '>':
+ entityName = "gt";
+ break;
+ default:
+ }
+ if (entityName == null) {
+ if (c > 0x7F) {
+ stringWriter.write("&#");
+ stringWriter.write(Integer.toString(c));
+ stringWriter.write(';');
+ } else {
+ stringWriter.write(c);
+ }
+ } else {
+ stringWriter.write('&');
+ stringWriter.write(entityName);
+ stringWriter.write(';');
+ }
+ }
+
+ return stringWriter.toString();
+ }
+
/**
* Write out the Commons SCXML object model using the supplied {@link Configuration}.
* Exactly one of the stream, writer or result parameters must be provided.
@@ -488,8 +541,8 @@ public class SCXMLWriter {
} else {
writer.writeStartElement(ELEM_DATA);
writeAV(writer, ATTR_ID, d.getId());
- writeAV(writer, ATTR_SRC, SCXMLHelper.escapeXML(d.getSrc()));
- writeAV(writer, ATTR_EXPR, SCXMLHelper.escapeXML(d.getExpr()));
+ writeAV(writer, ATTR_SRC, escapeXML(d.getSrc()));
+ writeAV(writer, ATTR_EXPR, escapeXML(d.getExpr()));
writer.writeEndElement();
}
}
@@ -527,7 +580,9 @@ public class SCXMLWriter {
writeInitial(writer, state.getInitial());
writeDatamodel(writer, state.getDatamodel());
writeHistory(writer, state.getHistory());
- writeOnEntry(writer, state.getOnEntry());
+ for (OnEntry onentry : state.getOnEntries()) {
+ writeOnEntry(writer, onentry);
+ }
for (Transition t : state.getTransitionsList()) {
writeTransition(writer, t);
@@ -547,7 +602,9 @@ public class SCXMLWriter {
}
}
- writeOnExit(writer, state.getOnExit());
+ for (OnExit onexit : state.getOnExits()) {
+ writeOnExit(writer, onexit);
+ }
writer.writeEndElement();
}
@@ -567,7 +624,9 @@ public class SCXMLWriter {
writeDatamodel(writer, parallel.getDatamodel());
writeHistory(writer, parallel.getHistory());
- writeOnEntry(writer, parallel.getOnEntry());
+ for (OnEntry onentry : parallel.getOnEntries()) {
+ writeOnEntry(writer, onentry);
+ }
for (Transition t : parallel.getTransitionsList()) {
writeTransition(writer, t);
@@ -587,7 +646,9 @@ public class SCXMLWriter {
}
}
- writeOnExit(writer, parallel.getOnExit());
+ for (OnExit onexit : parallel.getOnExits()) {
+ writeOnExit(writer, onexit);
+ }
writer.writeEndElement();
}
@@ -604,8 +665,12 @@ public class SCXMLWriter {
writer.writeStartElement(ELEM_FINAL);
writeTransitionTargetId(writer, end);
- writeOnEntry(writer, end.getOnEntry());
- writeOnExit(writer, end.getOnExit());
+ for (OnEntry onentry : end.getOnEntries()) {
+ writeOnEntry(writer, onentry);
+ }
+ for (OnExit onexit : end.getOnExits()) {
+ writeOnExit(writer, onexit);
+ }
writer.writeEndElement();
}
@@ -669,8 +734,9 @@ public class SCXMLWriter {
private static void writeOnEntry(final XMLStreamWriter writer, final OnEntry onentry)
throws XMLStreamException {
- if (onentry != null && onentry.getActions().size() > 0) {
+ if (onentry != null && (onentry.isRaiseEvent() || onentry.getActions().size() > 0 )) {
writer.writeStartElement(ELEM_ONENTRY);
+ writeAV(writer, ATTR_EVENT, onentry.getRaiseEvent());
writeExecutableContent(writer, onentry.getActions());
writer.writeEndElement();
}
@@ -687,8 +753,9 @@ public class SCXMLWriter {
private static void writeOnExit(final XMLStreamWriter writer, final OnExit onexit)
throws XMLStreamException {
- if (onexit != null && onexit.getActions().size() > 0) {
+ if (onexit != null && (onexit.isRaiseEvent() || onexit.getActions().size() > 0)) {
writer.writeStartElement(ELEM_ONEXIT);
+ writeAV(writer, ATTR_EVENT, onexit.getRaiseEvent());
writeExecutableContent(writer, onexit.getActions());
writer.writeEndElement();
}
@@ -708,7 +775,7 @@ public class SCXMLWriter {
writer.writeStartElement(ELEM_TRANSITION);
if (transition instanceof Transition) {
writeAV(writer, ATTR_EVENT, ((Transition)transition).getEvent());
- writeAV(writer, ATTR_COND, SCXMLHelper.escapeXML(((Transition)transition).getCond()));
+ writeAV(writer, ATTR_COND, escapeXML(((Transition)transition).getCond()));
}
writeAV(writer, ATTR_TARGET, transition.getNext());
@@ -735,11 +802,12 @@ public class SCXMLWriter {
writeAV(writer, ATTR_SRC, invoke.getSrc());
writeAV(writer, ATTR_SRCEXPR, invoke.getSrcexpr());
writeAV(writer, ATTR_TYPE, invoke.getType());
+ writeAV(writer, ATTR_AUTOFORWARD, invoke.getAutoForward());
for (Param p : invoke.params()) {
writer.writeStartElement(ELEM_PARAM);
writeAV(writer, ATTR_NAME, p.getName());
- writeAV(writer, ATTR_EXPR, SCXMLHelper.escapeXML(p.getExpr()));
+ writeAV(writer, ATTR_EXPR, escapeXML(p.getExpr()));
writer.writeEndElement();
}
writeFinalize(writer, invoke.getFinalize());
@@ -787,7 +855,7 @@ public class SCXMLWriter {
writeAV(writer, ATTR_LOCATION, asn.getLocation());
writeAV(writer, ATTR_NAME, asn.getName());
writeAV(writer, ATTR_SRC, asn.getSrc());
- writeAV(writer, ATTR_EXPR, SCXMLHelper.escapeXML(asn.getExpr()));
+ writeAV(writer, ATTR_EXPR, escapeXML(asn.getExpr()));
writer.writeEndElement();
} else if (a instanceof Send) {
writeSend(writer, (Send) a);
@@ -802,7 +870,7 @@ public class SCXMLWriter {
Log lg = (Log) a;
writer.writeStartElement(XMLNS_SCXML, ELEM_LOG);
writeAV(writer, ATTR_LABEL, lg.getLabel());
- writeAV(writer, ATTR_EXPR, SCXMLHelper.escapeXML(lg.getExpr()));
+ writeAV(writer, ATTR_EXPR, escapeXML(lg.getExpr()));
writer.writeEndElement();
} else if (a instanceof Raise) {
Raise e = (Raise) a;
@@ -821,13 +889,13 @@ public class SCXMLWriter {
} else if (a instanceof ElseIf) {
ElseIf eif = (ElseIf) a;
writer.writeStartElement(XMLNS_SCXML, ELEM_ELSEIF);
- writeAV(writer, ATTR_COND, SCXMLHelper.escapeXML(eif.getCond()));
+ writeAV(writer, ATTR_COND, escapeXML(eif.getCond()));
writer.writeEndElement();
} else if (a instanceof Var) {
Var v = (Var) a;
writer.writeStartElement(XMLNS_COMMONS_SCXML, ELEM_VAR);
writeAV(writer, ATTR_NAME, v.getName());
- writeAV(writer, ATTR_EXPR, SCXMLHelper.escapeXML(v.getExpr()));
+ writeAV(writer, ATTR_EXPR, escapeXML(v.getExpr()));
writer.writeEndElement();
} else {
writer.writeComment("Custom action with class name '" + a.getClass().getName() + "' not serialized");
@@ -872,7 +940,7 @@ public class SCXMLWriter {
throws XMLStreamException {
writer.writeStartElement(ELEM_IF);
- writeAV(writer, ATTR_COND, SCXMLHelper.escapeXML(iff.getCond()));
+ writeAV(writer, ATTR_COND, escapeXML(iff.getCond()));
writeExecutableContent(writer, iff.getActions());
writer.writeEndElement();
}
@@ -891,7 +959,7 @@ public class SCXMLWriter {
writer.writeStartElement(ELEM_FOREACH);
writeAV(writer, ATTR_ITEM, foreach.getItem());
writeAV(writer, ATTR_INDEX, foreach.getIndex());
- writeAV(writer, ATTR_ARRAY, SCXMLHelper.escapeXML(foreach.getArray()));
+ writeAV(writer, ATTR_ARRAY, escapeXML(foreach.getArray()));
writeExecutableContent(writer, foreach.getActions());
writer.writeEndElement();
}
@@ -960,6 +1028,22 @@ public class SCXMLWriter {
}
/**
+ * Write out this attribute, if the value is not <code>null</code>.
+ *
+ * @param writer The {@link XMLStreamWriter} in use for the serialization.
+ * @param localName The local name of the attribute.
+ * @param value The attribute value.
+ *
+ * @throws XMLStreamException An exception processing the underlying {@link XMLStreamWriter}.
+ */
+ private static void writeAV(final XMLStreamWriter writer, final String localName, final Boolean value)
+ throws XMLStreamException {
+ if (value != null) {
+ writer.writeAttribute(localName, value.toString());
+ }
+ }
+
+ /**
* Write the serialized SCXML document while making attempts to make the serialization human readable. This
* includes using new-lines and indentation as appropriate, where possible. Exactly one of the stream, writer
* or result parameters must be provided.
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Action.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Action.java?rev=1584272&r1=1584271&r2=1584272&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Action.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Action.java Thu Apr 3 07:13:42 2014
@@ -20,6 +20,7 @@ import java.io.Serializable;
import java.util.Map;
import org.apache.commons.scxml2.ActionExecutionContext;
+import org.apache.commons.scxml2.Context;
import org.apache.commons.scxml2.SCXMLExpressionException;
/**
@@ -42,12 +43,6 @@ public abstract class Action implements
private Map<String, String> namespaces;
/**
- * Current document namespaces are saved under this key in the parent
- * state's context.
- */
- private static final String NAMESPACES_KEY = "_ALL_NAMESPACES";
-
- /**
* Constructor.
*/
public Action() {
@@ -137,7 +132,7 @@ public abstract class Action implements
* @return The namespaces key
*/
protected static String getNamespacesKey() {
- return NAMESPACES_KEY;
+ return Context.NAMESPACES_KEY;
}
}
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Assign.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Assign.java?rev=1584272&r1=1584271&r2=1584272&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Assign.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/Assign.java Thu Apr 3 07:13:42 2014
@@ -28,11 +28,9 @@ import org.apache.commons.scxml2.Context
import org.apache.commons.scxml2.Evaluator;
import org.apache.commons.scxml2.PathResolver;
import org.apache.commons.scxml2.SCXMLExpressionException;
-import org.apache.commons.scxml2.SCXMLHelper;
import org.apache.commons.scxml2.TriggerEvent;
import org.apache.commons.scxml2.semantics.ErrorConstants;
-import org.w3c.dom.Document;
-import org.w3c.dom.Node;
+import org.w3c.dom.*;
import org.xml.sax.SAXException;
/**
@@ -181,7 +179,7 @@ public class Assign extends Action imple
Evaluator eval = exctx.getEvaluator();
ctx.setLocal(getNamespacesKey(), getNamespaces());
// "location" gets preference over "name"
- if (!SCXMLHelper.isStringEmpty(location)) {
+ if (location != null) {
Node oldNode = eval.evalLocation(ctx, location);
if (oldNode != null) {
//// rvalue may be ...
@@ -213,7 +211,7 @@ public class Assign extends Action imple
} catch (SCXMLExpressionException see) {
// or something else, stuff toString() into lvalue
Object valueObject = eval.eval(ctx, expr);
- SCXMLHelper.setNodeValue(oldNode, valueObject.toString());
+ setNodeValue(oldNode, valueObject.toString());
}
if (exctx.getAppLog().isDebugEnabled()) {
exctx.getAppLog().debug("<assign>: data node '" + oldNode.getNodeName()
@@ -253,6 +251,43 @@ public class Assign extends Action imple
}
/**
+ * Set node value, depending on its type, from a String.
+ *
+ * @param node A Node whose value is to be set
+ * @param value The new value
+ */
+ private void setNodeValue(final Node node, final String value) {
+ switch(node.getNodeType()) {
+ case Node.ATTRIBUTE_NODE:
+ node.setNodeValue(value);
+ break;
+ case Node.ELEMENT_NODE:
+ //remove all text children
+ if (node.hasChildNodes()) {
+ Node child = node.getFirstChild();
+ while (child != null) {
+ if (child.getNodeType() == Node.TEXT_NODE) {
+ node.removeChild(child);
+ }
+ child = child.getNextSibling();
+ }
+ }
+ //create a new text node and append
+ Text txt = node.getOwnerDocument().createTextNode(value);
+ node.appendChild(txt);
+ break;
+ case Node.TEXT_NODE:
+ case Node.CDATA_SECTION_NODE:
+ ((CharacterData) node).setData(value);
+ break;
+ default:
+ String err = "Trying to set value of a strange Node type: "
+ + node.getNodeType();
+ throw new IllegalArgumentException(err);
+ }
+ }
+
+ /**
* Get the {@link Node} the "src" attribute points to.
*
* @return The node the "src" attribute points to.
Modified: commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/CustomAction.java
URL: http://svn.apache.org/viewvc/commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/CustomAction.java?rev=1584272&r1=1584271&r2=1584272&view=diff
==============================================================================
--- commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/CustomAction.java (original)
+++ commons/proper/scxml/trunk/src/main/java/org/apache/commons/scxml2/model/CustomAction.java Thu Apr 3 07:13:42 2014
@@ -17,7 +17,6 @@
package org.apache.commons.scxml2.model;
import org.apache.commons.logging.LogFactory;
-import org.apache.commons.scxml2.SCXMLHelper;
import org.apache.commons.logging.Log;
@@ -92,7 +91,7 @@ public class CustomAction {
public CustomAction(final String namespaceURI, final String localName,
final Class<? extends Action> actionClass) {
Log log = LogFactory.getLog(CustomAction.class);
- if (SCXMLHelper.isStringEmpty(namespaceURI)) {
+ if (namespaceURI == null || namespaceURI.trim().length() == 0) {
log.error(ERR_NO_NAMESPACE);
throw new IllegalArgumentException(ERR_NO_NAMESPACE);
}
@@ -100,12 +99,11 @@ public class CustomAction {
log.error(ERR_RESERVED_NAMESPACE);
throw new IllegalArgumentException(ERR_RESERVED_NAMESPACE);
}
- if (SCXMLHelper.isStringEmpty(localName)) {
+ if (localName == null || localName.trim().length() == 0) {
log.error(ERR_NO_LOCAL_NAME);
throw new IllegalArgumentException(ERR_NO_LOCAL_NAME);
}
- if (actionClass == null
- || !Action.class.isAssignableFrom(actionClass)) {
+ if (actionClass == null || !Action.class.isAssignableFrom(actionClass)) {
log.error(ERR_NOT_AN_ACTION);
throw new IllegalArgumentException(ERR_NOT_AN_ACTION);
}