001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.scxml2;
018
019import java.util.Set;
020
021import org.apache.commons.scxml2.model.EnterableState;
022import org.apache.commons.scxml2.model.ModelException;
023import org.apache.commons.scxml2.model.SCXML;
024
025/**
026 * <p>The purpose of this interface is to separate the the
027 * <a href="http://www.w3.org/TR/2014/CR-scxml-20140313/#AlgorithmforSCXMLInterpretation">
028 *     W3C SCXML Algorithm for SCXML Interpretation</a>
029 * from the <code>SCXMLExecutor</code> and therefore make it pluggable.</p>
030 * <p>
031 * From an SCXML execution POV, there are only three entry points needed into the Algorithm, namely:
032 * <ul>
033 *     <li>Performing the initialization of the state machine and completing a first macro step,
034 *     see: {@link #firstStep(SCXMLExecutionContext)}. The state machine thereafter should be ready
035 *     for processing external events (or be terminated already)</li>
036 *     <li>Processing a single external event and completing the macro step for it, after which the
037 *     state machine should be ready for processing another external event (if any), or be terminated already.
038 *     See: {@link #nextStep(SCXMLExecutionContext, TriggerEvent)}.
039 *     </li>
040 *     <li>Finally, if the state machine terminated ({@link SCXMLExecutionContext#isRunning()} == false), after either
041 *     of the above steps, finalize the state machine by performing the final step.
042 *     See: {@link #finalStep(SCXMLExecutionContext)}.
043 *     </li>
044 * </ul>
045 * </p>
046 * <p>After a state machine has been terminated you can re-initialize the execution context, and start again.</p>
047 * <p>
048 * Except for the loading of the SCXML document and (re)initializing the {@link SCXMLExecutionContext}, the above steps
049 * represent the <b>interpret</b>,<b>mainEventLoop</b> and <b>exitInterpreter</b> entry points specified in Algorithm
050 * for SCXML Interpretation, but more practically and logically broken into separate steps so that the blocking wait
051 * for external events can be handled externally.
052 * </p>
053 * <p>
054 *  These three entry points are the only interface methods used by the SCXMLExecutor. It is up to the
055 *  specific SCXMLSemantics implementation to provide the concrete handling for these according to the Algorithm in
056 *  the SCXML specification (or possibly something else/different).
057 * </p>
058 * <p>
059 * The default {@link org.apache.commons.scxml2.semantics.SCXMLSemanticsImpl} provides an implementation of the
060 * specification, and can easily be overridden/customized as a whole or only on specific parts of the Algorithm
061 * implementation.
062 * </p>
063 * <p>
064 * Note that both the {@link #firstStep(SCXMLExecutionContext)} and {@link #nextStep(SCXMLExecutionContext, TriggerEvent)}
065 * first run to completion for any internal events raised before returning, as expected and required by the SCXML
066 * specification, so it is currently not possible to 'manage' internal event processing externally.
067 * </p>
068 *
069 * <p>Specific semantics can be created by subclassing
070 * <code>org.apache.commons.scxml2.semantics.SCXMLSemanticsImpl</code>.</p>
071 */
072public interface SCXMLSemantics {
073
074    /**
075     * Optional post processing immediately following SCXMLReader. May be used
076     * for removing pseudo-states etc.
077     *
078     * @param input  SCXML state machine
079     * @param errRep ErrorReporter callback
080     * @return normalized SCXML state machine, pseudo states are removed, etc.
081     */
082    SCXML normalizeStateMachine(final SCXML input, final ErrorReporter errRep);
083
084    /**
085     * First step in the execution of an SCXML state machine.
086     * <p>
087     * In the default implementation, this will first (re)initialize the state machine instance, destroying any existing
088     * state!
089     * </p>
090     * <p>
091     * The first step is corresponding to the Algorithm for SCXML processing from the interpret() procedure to the
092     * mainLoop() procedure up to the blocking wait for an external event.
093     * </p>
094     * <p>
095     * This step should complete the SCXML initial execution and a subsequent macroStep to stabilize the state machine
096     * again before returning.
097     * </p>
098     * <p>
099     * If the state machine no longer is running after all this, first the {@link #finalStep(SCXMLExecutionContext)}
100     * should be called for cleanup before returning.
101     * </p>
102     * @param exctx The execution context for this step
103     * @throws ModelException if the state machine instance failed to initialize or a SCXML model error occurred during
104     * the execution.
105     */
106    void firstStep(final SCXMLExecutionContext exctx) throws ModelException;
107
108    /**
109     * Next step in the execution of an SCXML state machine.
110     * <p>
111     * The next step is corresponding to the Algorithm for SCXML processing mainEventLoop() procedure after receiving an
112     * external event, up to the blocking wait for another external event.
113     * </p>
114     * <p>
115     * If the state machine isn't {@link SCXMLExecutionContext#isRunning()} (any more), this method should do nothing.
116     * </p>
117     * <p>
118     * If the provided event is a {@link TriggerEvent#CANCEL_EVENT}, the state machine should stop running.
119     * </p>
120     * <p>
121     * Otherwise, the event must be set in the {@link SCXMLSystemContext} and processing of the event then should start,
122     * and if the event leads to any transitions a microStep for this event should be performed, followed up by a
123     * macroStep to stabilize the state machine again before returning.
124     * </p>
125     * <p>
126     * If the state machine no longer is running after all this, first the {@link #finalStep(SCXMLExecutionContext)}
127     * should be called for cleanup before returning.
128     * </p>
129     * @param exctx The execution context for this step
130     * @param event The event to process
131     * @throws ModelException if a SCXML model error occurred during the execution.
132     */
133    void nextStep(final SCXMLExecutionContext exctx, final TriggerEvent event) throws ModelException;
134
135    /**
136     * The final step in the execution of an SCXML state machine.
137     * <p>
138     * This final step is corresponding to the Algorithm for SCXML processing exitInterpreter() procedure, after the
139     * state machine stopped running.
140     * </p>
141     * <p>
142     * If the state machine still is {@link SCXMLExecutionContext#isRunning()} invoking this method should simply
143     * do nothing.
144     * </p>
145     * <p>
146     * This final step should first exit all remaining active states and cancel any active invokers, before handling
147     * the possible donedata element for the last final state.
148     * </p>
149     * <p>
150     *  <em>NOTE: the current implementation does not yet provide final donedata handling.</em>
151     * </p>
152     * @param exctx The execution context for this step
153     * @throws ModelException if a SCXML model error occurred during the execution.
154     */
155    void finalStep(final SCXMLExecutionContext exctx) throws ModelException;
156
157    /**
158     * Checks whether a given set of states is a legal Harel State Table
159     * configuration (with the respect to the definition of the OR and AND
160     * states).
161     * <p>
162     * When {@link SCXMLExecutionContext#isCheckLegalConfiguration()} is true (default) the SCXMLSemantics implementation
163     * <em>should</em> invoke this method before executing a step, and throw a ModelException if a non-legal
164     * configuration is encountered.
165     * </p>
166     * <p>
167     * This method is also first invoked when manually initializing the status of a state machine through
168     * {@link SCXMLExecutor#setConfiguration(java.util.Set}.
169     * </p>
170     * @param states a set of states
171     * @param errRep ErrorReporter to report detailed error info if needed
172     * @return true if a given state configuration is legal, false otherwise
173     */
174    public boolean isLegalConfiguration(final Set<EnterableState> states, final ErrorReporter errRep);
175}