Author: jbeard
Date: Tue Jun 22 15:52:33 2010
New Revision: 956932
URL: http://svn.apache.org/viewvc?rev=956932&view=rev
Log:
Checking in preprocessed stylesheets. Later on this will need to be made part
of the build process.
Added:
commons/sandbox/gsoc/2010/scxml-js/branches/browser-tests.1.ie/src/xslt/backends/js/StateTableStatechartGenerator_combined.xsl
(with props)
commons/sandbox/gsoc/2010/scxml-js/branches/browser-tests.1.ie/src/xslt/backends/js/SwitchyardStatechartGenerator_combined.xsl
(with props)
Added:
commons/sandbox/gsoc/2010/scxml-js/branches/browser-tests.1.ie/src/xslt/backends/js/StateTableStatechartGenerator_combined.xsl
URL:
http://svn.apache.org/viewvc/commons/sandbox/gsoc/2010/scxml-js/branches/browser-tests.1.ie/src/xslt/backends/js/StateTableStatechartGenerator_combined.xsl?rev=956932&view=auto
==============================================================================
---
commons/sandbox/gsoc/2010/scxml-js/branches/browser-tests.1.ie/src/xslt/backends/js/StateTableStatechartGenerator_combined.xsl
(added)
+++
commons/sandbox/gsoc/2010/scxml-js/branches/browser-tests.1.ie/src/xslt/backends/js/StateTableStatechartGenerator_combined.xsl
Tue Jun 22 15:52:33 2010
@@ -0,0 +1,731 @@
+<?xml version="1.0" encoding="UTF-8"?><!--
+ * 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.
+--><stylesheet xmlns="http://www.w3.org/1999/XSL/Transform"
xmlns:s="http://www.w3.org/2005/07/scxml" xmlns:c="urn://scxml-js"
version="1.0">
+
+ <output method="text"/><param name="log" select="true()"/><param
name="noIndexOf" select="false()"/><param name="noMap" select="false()"/><param
name="noForEach" select="false()"/><param name="name"/><variable
name="allStates" select="//*[(self::s:state or self::s:parallel or
self::s:final or self::s:initial or self::s:scxml or
self::s:history)]"/><variable name="states" select="//s:state"/><variable
name="transitions" select="//s:transition"/><variable name="basicStates"
select="$allStates[not(.//*[(self::s:state or self::s:parallel or self::s:final
or self::s:initial or self::s:scxml or self::s:history)])]"/><variable
name="compositeStates" select="$allStates[.//*[(self::s:state or
self::s:parallel or self::s:final or self::s:initial or self::s:scxml or
self::s:history)]]"/><variable name="eventsEnum"
select="/s:scxml/c:eventsEnum/c:event"/><template match="/s:scxml">
+
+ <if test="$noIndexOf">
+ <call-template
name="genNoIndexOfArrayPrototypeExtension"/>
+ </if>
+
+ <if test="$noMap">
+ <call-template name="genNoMapArrayPrototypeExtension"/>
+ </if>
+
+ <if test="$noForEach">
+ <call-template
name="genNoForEachArrayPrototypeExtension"/>
+ </if>
+
+ function <value-of select="$name"/>StatechartExecutionContext(){
+
+ var self = this; //used in the rare
occasions we call public functions from inside this class
+
+ //abstract state
+
+ <call-template name="genAbstractState">
+ <with-param name="events"
select="$eventsEnum"/>
+ </call-template>
+
+ //states
+ <for-each select="$allStates">
+ <call-template name="genState">
+ <with-param name="state"
select="."/>
+ </call-template>
+ </for-each>
+
+
+ //states enum for glass-box unit testing
+ <call-template name="genStatesEnum">
+ <with-param name="states"
select="$basicStates"/>
+ </call-template>
+
+ //trigger methods for synchronous interaction
+ <for-each select="$eventsEnum">
+ <call-template
name="genExternalTriggerDispatcher">
+ <with-param name="event"
select="."/>
+ </call-template>
+ </for-each>
+
+ <call-template name="genContextHooks"/>
+
+ //initialization script
+ <value-of select="s:script"/>
+
+ //initialization method
+ <call-template name="genInitialization"/>
+
+ //internal runtime functions
+ <call-template
name="genInternalRuntimeFunctions"/>
+
+ //start static boilerplate code
+ <call-template
name="genBoilerplateDispatchCode"/>
+
+ }
+
+ </template><template name="genAbstractState">
+ <param name="events"/>
+
+ var AbstractState = new function(){
+ //triggers are methods
+
+ <for-each select="$events">
+ this.<value-of select="./c:name"/> =
function(){};
+ </for-each>
+
+ this.$default = function(){};
+ }
+ </template><template name="genState">
+ <param name="state"/>
+
+ <variable name="stateName" select="$state/@id"/>
+
+ <variable name="parentName">
+ <choose>
+ <!-- FIXME: probably want to refine this query,
as we may not be able to assume that all states have ids?-->
+ <when test="$state/../@id">
+ <value-of select="$state/../@id"/>
+ </when>
+ <otherwise>
+ <value-of select="'AbstractState'"/>
+ </otherwise>
+ </choose>
+ </variable>
+
+ <variable name="historyState" select="$state/s:history"/>
+
+ <variable name="constructorFunctionName"
select="concat($stateName,'Constructor')"/>
+
+ <!--
+ var stateName = sta...@id;
+ var parentName = state.parent() ?
state.parent()....@id : "AbstractState";
+ var historyState = state.history;
+ var hasHistoryState =
historyState.length() > 0;
+ var constructorFunctionName = stateName
+ "Constructor";
+ -->
+
+ var <value-of select="$stateName"/> = (function(){
+
+ function <value-of
select="$constructorFunctionName"/>(){
+ this.parent = <value-of select="$parentName"/>;
+
+ this.initial = null;
+
+ this.depth = <value-of
select="count($state/ancestor::*)"/>;
+
+ this.historyState = null;
+
+ <if test="$state/self::s:history">
+ this.parent.historyState = this; //init
parent's pointer to history state
+ </if>
+
+ <if test="$state/self::s:initial">
+ this.parent.initial = this; //init
parent's pointer to initial state
+ </if>
+
+ this.toString = function(){
+ return "<value-of select="$stateName"/>"
+ }
+
+ this.enterAction = function(){
+ <if test="$log">
+ console.log("entering <value-of
select="$stateName"/>");
+ </if>
+
+ <apply-templates
select="$state/s:onentry/*[self::s:if or self::s:raise or self::s:log or
self::s:script or self::s:send or self::s:cancel or self::s:invoke or
self::s:finalize or self::s:datamodel or self::s:data or self::s:assign or
self::s:validate or self::s:param]"/>
+ }
+
+ this.exitAction = function(){
+ <if test="$log">
+ console.log("exiting <value-of
select="$stateName"/>" );
+ </if>
+
+ <if test="$historyState">
+
this.historyState.lastConfiguration = currentConfiguration.slice();
+ </if>
+
+ <apply-templates
select="$state/s:onexit/*[self::s:if or self::s:raise or self::s:log or
self::s:script or self::s:send or self::s:cancel or self::s:invoke or
self::s:finalize or self::s:datamodel or self::s:data or self::s:assign or
self::s:validate or self::s:param]"/>
+ }
+
+ <call-template name="genStateHooks">
+ <with-param name="state"
select="$state"/>
+ </call-template>
+
+
+ }
+ <value-of select="$constructorFunctionName"/>.prototype
= <value-of select="$parentName"/>;
+ return new <value-of
select="$constructorFunctionName"/>();
+ })();
+
+ </template><template name="genStatesEnum">
+ <param name="states"/>
+
+ this._states = {
+ <for-each select="$states">
+ <value-of select="@id"/> : <value-of
select="@id"/>
+ <if test="not(position() = last())">,</if>
+ </for-each>
+ }
+
+ </template><template match="s:if">
+ if (<value-of select="@cond"/>) {
+ <apply-templates select="c:executableContent/*"/>
+ }
+ <apply-templates select="s:elseif"/>
+ <apply-templates select="s:else"/>
+ </template><template match="s:elseif">
+ else if (<value-of select="@cond"/>) {
+ <apply-templates select="c:executableContent/*"/>
+ }
+ </template><template match="s:else">
+ else {
+ <apply-templates select="c:executableContent/*"/>
+ }
+ </template><template match="s:log">
+ <if test="@label">
+ console.log( ' <value-of select="@label"/> : ' );
+ </if>
+ <if test="@expr">
+ console.log( <value-of select="@expr"/> );
+
+ </if>
+ </template><template match="s:raise">
+ <!--TODO-->
+ </template><template match="s:script">
+ <value-of select="."/>
+ </template><template match="s:cancel">
+ <!--TODO-->
+ </template><template match="s:invoke">
+ <!--TODO-->
+ </template><template match="s:finalize">
+ <!--TODO-->
+ </template><template match="s:datamodel">
+ <!--TODO-->
+ </template><template match="s:data">
+ <!--TODO-->
+ </template><template match="s:assign">
+ <!--TODO-->
+ </template><template match="s:validate">
+ <!--TODO-->
+ </template><template match="s:param">
+ <!--TODO-->
+ </template><template name="genInternalRuntimeFunctions">
+ function sortByDepthDeepToShallow(a,b){
+ return b.depth - a.depth;
+ }
+ </template><template name="genBoilerplateDispatchCode">
+ //static private member variables
+ var currentConfiguration = []; //current configuration
+ var innerEventQueue = []; //inner event queue
+ var outerEventQueue = []; //outer event queue
+ var isInStableState = true;
+ var isPreempted = false;
+ var hasTakenDefaultTransition = false;
+ var destroyed = false;
+ var mainLoopCallback = null;
+
+ //static private member functions
+ function mainLoop() {
+
+ if(!destroyed){
+ //take an event from the current outer event
queue
+ if (outerEventQueue.length &&
isInStableState) {
+
runToCompletion(outerEventQueue.shift());
+ }
+ //call back
+ mainLoopCallback = window.setTimeout(function()
{
+ mainLoop(); //FIXME: note that when
calling mainloop this way, we won't have access to the "this" object.
+ //I don't think we ever use it though.
Everything we need is private in function scope.
+ },
+ 100);
+ }
+ }
+
+ function runToCompletion(e){
+ isInStableState = false;
+
+ if(e){
+ innerEventQueue.push(e);
+ }
+
+ do{
+ //take any available default transitions
+ microstep(<value-of
select="$defaultEventLiteral"/>);
+
+ if(!hasTakenDefaultTransition){
+
+ if(!innerEventQueue.length){
+ //we have no more generated
events, and no default transitions fired, so
+ //we are done, and have run to
completion
+ break;
+ }else{
+ //microstep, then dequeue next
event sending in event
+
microstep(innerEventQueue.shift());
+ }
+ }else{
+ //he has taken a default transition, so
reset the global variable to false and loop again
+ hasTakenDefaultTransition = false;
+ }
+
+ }while(true)
+
+ isInStableState = true;
+ }
+
+ function microstep(e){
+ currentConfiguration.forEach(function(state){
+ if(!isPreempted)
+ <value-of select="$dispatchInvocation"/>
+ });
+
+ //reset the isPreempted flag
+ isPreempted = false;
+ }
+
+
+ this.destroy = function(){
+ //right now, this only disables timer and sets global
destroyed variable to prevent future callbacks
+ window.clearTimeout(mainLoopCallback);
+ mainLoopCallback = null;
+ destroyed = true;
+ }
+
+
+ //this is for async communication
+ this.GEN = function(e){
+ outerEventQueue.push(e);
+ }
+
+ //this may or may not be something we want to expose, but for
right now, we at least need it for testing
+ this.getCurrentConfiguration = function(){
+ //slice it to return a copy of the configuration rather
than the conf itself
+ //this saves us all kinds of confusion involving
references and stuff
+ return <value-of
select="$currentConfigurationExpression"/>;
+ }
+
+ //end static boilerplate code
+ </template><variable name="deepHistoryEnterAction">
+ <text>
+ var topState;
+ while(topState = statesEntered.pop()){
+ topState.enterAction();
+ }
+ </text>
+ </variable><variable name="shallowHistoryEnterAction">
+ <text>
+ var topState = statesEntered.pop();
+
+ topState.enterAction();
+
+ newConfiguration.push(topState.initial ?
topState.initial : topState );
+ </text>
+ </variable><variable
name="genNonBasicTriggerDispatcherExitBlockInnerForEach">
+ <text>
+ do{
+ statesExited.push(state);
+ }while((state = state.parent) &&
+ state != lca &&
+ statesExited.indexOf(state) == -1)
+ </text>
+ </variable><template name="genHistoryTriggerDispatcher">
+ <param name="s"/>
+ <param name="t"/>
+
+ <variable name="isDeep" select="$s/@type = 'deep'"/>
+ <variable name="historyStateReference">
+ <call-template
name="genHistoryTriggerDispatcherHistoryStateReference">
+ <with-param name="s" select="$s"/>
+ </call-template>
+ </variable>
+
+
+ //history state semantics
+ if(<value-of
select="$historyStateReference"/>.lastConfiguration){
+
+ //transition action
+ <if test="$log">
+ <choose>
+ <when test="$isDeep">
+ console.log("return to last
deep configuration");
+ </when>
+ <otherwise>
+ console.log("return to last
shallow configuration");
+ </otherwise>
+ </choose>
+ </if>
+
+
+ <!--gen executable content for t-->
+ <apply-templates select="$t/*[self::s:if or
self::s:raise or self::s:log or self::s:script or self::s:send or
self::s:cancel or self::s:invoke or self::s:finalize or self::s:datamodel or
self::s:data or self::s:assign or self::s:validate or self::s:param]"/>
+
+
+
+ var historyState = <value-of
select="$historyStateReference"/>;
+
+ <if test="not($isDeep)">
+ var newConfiguration = [];
+ </if>
+
+ <value-of
select="$historyStateReference"/>.lastConfiguration.forEach(function(state){
+ <call-template
name="genHistoryTriggerDispatcherInnerForEach">
+ <with-param name="isDeep"
select="$isDeep"/>
+ </call-template>
+ });
+
+ <choose>
+ <when test="$isDeep">
+ currentConfiguration = <value-of
select="$historyStateReference"/>.lastConfiguration.slice();
+ </when>
+ <otherwise>
+ currentConfiguration = <value-of
select="$genHistoryTriggerDispatcherCurrentConfigurationAssignmentRHS"/>;
+ </otherwise>
+ </choose>
+
+ }else{
+ <call-template name="genTriggerDispatcherContents">
+ <with-param name="s" select="$s"/>
+ <with-param name="t" select="$t"/>
+ </call-template>
+ }
+ </template><template name="genHistoryTriggerDispatcherInnerForEach">
+ <param name="isDeep"/>
+
+ var statesEntered = [<value-of
select="$genHistoryTriggerDispatcherInnerForEachStateReference"/>];
+
+ for(var parent = <value-of
select="$genHistoryTriggerDispatcherInnerForEachStateReference"/>.parent;
+ parent != historyState.parent && parent !=
null;
+ parent = parent.parent){
+ statesEntered.push(parent);
+ }
+
+
+ <choose>
+ <when test="$isDeep">
+ <value-of select="$deepHistoryEnterAction"/>
+ </when>
+ <otherwise>
+ <value-of select="$shallowHistoryEnterAction"/>
+ </otherwise>
+ </choose>
+ </template><template name="genNonBasicTriggerDispatcherExitBlock">
+ <param name="t"/>
+
+ var statesExited = [];
+ var lca = <value-of select="$t/c:lca"/>;
+
+ <value-of
select="$genNonBasicTriggerDispatcherExitBlockIteratorExpression"/>.forEach(function(state){
+ <value-of
select="$genNonBasicTriggerDispatcherExitBlockInnerForEach"/>
+ });
+
+ //sort by depth
+ statesExited.sort(sortByDepthDeepToShallow);
+
+ //execute actions for each of these states
+ statesExited.forEach(function(state){
+ state.exitAction();
+ });
+ </template><template name="genTriggerDispatcherContents">
+ <param name="s"/>
+ <param name="t"/>
+
+ <if test="not($t/@event)">
+ hasTakenDefaultTransition = true;
+ </if>
+
+ //exit states
+ <choose>
+ <when test="local-name($s) = 'initial' or
local-name($s) = 'history' or ( $s/@c:isBasic and (
not($s/@c:isParallelSubstate) or ($s/@c:isParallelSubstate and
not($t/@c:exitsParallelRegion))))">
+ <for-each select="$t/c:exitpath/c:state">
+ <value-of select="."/>.exitAction();
+ </for-each>
+ </when>
+ <otherwise>
+ <call-template
name="genNonBasicTriggerDispatcherExitBlock">
+ <with-param name="t" select="$t"/>
+ </call-template>
+ </otherwise>
+ </choose>
+
+ //transition action
+ <apply-templates select="$t/*[self::s:if or self::s:raise or
self::s:log or self::s:script or self::s:send or self::s:cancel or
self::s:invoke or self::s:finalize or self::s:datamodel or self::s:data or
self::s:assign or self::s:validate or self::s:param]"/>
+
+ //enter states
+ <for-each select="$t/c:targets/c:target/c:enterpath/c:state">
+ <!-- iterate in reverse order -->
+ <sort select="position()" data-type="number"
order="descending"/>
+ <value-of select="."/>.enterAction();
+ </for-each>
+
+ //update configuration
+ <choose>
+ <when test="$s/@c:isParallelSubstate and
not($t/@c:exitsParallelRegion)">
+ <call-template
name="genParallelSubstateConfigurationSetString">
+ <with-param name="s" select="$s"/>
+ <with-param name="t" select="$t"/>
+ </call-template>
+ </when>
+ <otherwise>
+ <call-template
name="genNonParallelSubstateConfigurationSetString">
+ <with-param name="s" select="$s"/>
+ <with-param name="t" select="$t"/>
+ </call-template>
+ </otherwise>
+ </choose>
+
+
+ //set whether preempted
+ <if test="$t/@c:isPreempted">
+ isPreempted = true;
+ </if>
+ </template><template name="genNoForEachArrayPrototypeExtension">
+ if(!Array.forEach){
+ Array.prototype.forEach = function(fn){
+ for(var i=0; i < this.length; i++){
+ fn(this[i]);
+ }
+ return undefined;
+ }
+ }
+ </template><template name="genNoIndexOfArrayPrototypeExtension">
+ if(!Array.indexOf){
+ Array.prototype.indexOf = function(obj){
+ for(var i=0; i < this.length; i++){
+ if(this[i]==obj){
+ return i;
+ }
+ }
+ return -1;
+ }
+ }
+ </template><template name="genNoMapArrayPrototypeExtension">
+ if(!Array.map){
+ Array.prototype.map = function(fn){
+ var toReturn = [];
+ for(var i=0; i < this.length; i++){
+ toReturn[i]=fn(this[i]);
+ }
+ return toReturn;
+ }
+ }
+ </template><param name="defaultEventLiteral"
select="'$default'"/><param name="currentConfigurationExpression"
select="'currentConfiguration.map(function(s){return
STATE_INT_ID_TO_OBJECT_MAP[s]})'"/><param
name="genHistoryTriggerDispatcherCurrentConfigurationAssignmentRHS"
select="'newConfiguration.map(function(sObj){return sObj.id})'"/><param
name="genHistoryTriggerDispatcherInnerForEachStateReference"
select="'STATE_INT_ID_TO_OBJECT_MAP[state]'"/><param
name="genNonBasicTriggerDispatcherExitBlockIteratorExpression"
select="'currentConfiguration.map(function(state){return
STATE_INT_ID_TO_OBJECT_MAP[state]})'"/><template name="genContextHooks">
+ //enumeration of states int id's
+ <for-each select="$basicStates">
+ var <value-of select="@c:enumId"/> = <value-of
select="@c:stateNum - 1"/>;
+ </for-each>
+
+ //map from states int id's to objects
+ var STATE_INT_ID_TO_OBJECT_MAP = [
+ <for-each select="$basicStates">
+ <value-of select="@id"/> <if test="not(position() =
last())"> , </if>
+ </for-each> ];
+
+ //tag each state object with an int id to map from object to id
+ //only needed for history
+ <for-each select="$basicStates">
+ <value-of select="@id"/>.id = <value-of
select="@c:stateNum - 1"/>;
+ </for-each>
+
+ //enumeration of triggers
+ <for-each select="$eventsEnum">
+ var <value-of select="c:name"/> = <value-of
select="c:id"/>;
+ </for-each>
+
+ //expose them as a convenient interface as part of the API
+ <call-template name="genTriggerExternalObject"/>
+
+ //needed for debugging
+ <call-template name="genTriggerIdToNameMap"/>
+
+ //transition functions
+ <for-each select="$transitions">
+ <call-template name="genTriggerDispatcherContext">
+ <with-param name="s" select=".."/>
+ <with-param name="t" select="."/>
+ </call-template>
+ </for-each>
+
+ <call-template name="genEnumeratedHooks"/>
+ </template><template name="genTriggerExternalObject">
+ this.TRIGGERS = {
+ <for-each select="$eventsEnum">
+ <value-of select="c:name"/> : <value-of
select="c:name"/>
+ <if test="not(position() = last())"> ,
</if>
+ </for-each>
+ };
+ </template><template name="genTriggerIdToNameMap">
+ var TRIGGER_ID_TO_NAME_MAP = [
+ <for-each select="$eventsEnum">
+ '<value-of select="c:name"/>'
+ <if test="not(position() = last())"> , </if>
+ </for-each>
+ ];
+ </template><template name="genTriggerDispatcherContext">
+ <param name="s"/>
+ <param name="t"/>
+
+ var <value-of select="$t/@c:tName"/> = function(){
+ <choose>
+ <when test="$s/@c:isHistory">
+ <call-template
name="genHistoryTriggerDispatcher">
+ <with-param name="s"
select="$s"/>
+ <with-param name="t"
select="$t"/>
+ </call-template>
+ </when>
+ <otherwise>
+ <call-template
name="genTriggerDispatcherContents">
+ <with-param name="s"
select="$s"/>
+ <with-param name="t"
select="$t"/>
+ </call-template>
+ </otherwise>
+ </choose>
+ }
+ </template><template name="genExternalTriggerDispatcher">
+ <param name="event"/>
+
+ this.<value-of select="$event/c:name"/> = function(){
+ if(isInStableState){
+ runToCompletion(<value-of
select="$event/c:name"/>);
+ }else{
+ return undefined;
+ }
+ }
+ </template><template
name="genNonParallelSubstateConfigurationSetString">
+ <param name="t"/>
+
+ currentConfiguration = [
+ <for-each select="$t/c:targets/c:target/c:targetState">
+ <variable name="targetStateId" select="."/>
+ <value-of select="$allstat...@id =
$targetStateId]/@c:enumId"/>
+
+ <if test="not(position() = last())"> , </if>
+ </for-each>
+ ];
+ </template><template name="genParallelSubstateConfigurationSetString">
+ <param name="s"/>
+ <param name="t"/>
+
+
currentConfiguration.splice(currentConfiguration.indexOf(<value-of
select="$s/@c:enumId"/>),1,
+ <for-each select="$t/c:targets/c:target/c:targetState">
+ <variable name="targetStateId" select="."/>
+ <value-of select="$allstat...@id =
$targetStateId]/@c:enumId"/>
+
+ <if test="not(position() = last())"> , </if>
+ </for-each>);
+ </template><template name="genInitialization">
+ <!-- we just need to know what the initial state is -->
+ <variable name="initialStateName" select="$allstat...@id =
/s:scxml/s:initial/s:transition/c:targets/c:target/c:targetState]/@c:enumId"/>
+
+ this.initialize = function(){
+ currentConfiguration = [<value-of
select="$initialStateName"/>];
+ runToCompletion();
+ mainLoop();
+ }
+ </template><template match="s:send">
+ <variable name="sendEvent" select="@event"/>
+ <variable name="sendDelay" select="number(@delay)"/>
+
+ <choose>
+ <when test="$sendDelay">
+ //set timeout
+ toReturn = window.setTimeout(function(){
+ self.GEN(<value-of
select="$sendEvent"/>);
+ }, <value-of select="$sendDelay*1000"/>);
+ </when>
+ <otherwise>
+ //just add the event to the outer queue
+ toReturn = innerEventQueue.push(<value-of
select="$sendEvent"/>);
+ </otherwise>
+ </choose>
+ </template><template
name="genHistoryTriggerDispatcherHistoryStateReference">
+ <param name="s"/>
+
+ <value-of select="$s/@id"/>
+ </template><template name="genStateHooks"/><template
name="genTriggerIntEnum"/>
+
+ <param name="dispatchInvocation"
select="'STATE_TRANSITION_TABLE[state][e]();'"/>
+
+ <variable name="nullTransitionFunctionName" select="'$nt'"/>
+
+ <template name="genEnumeratedHooks">
+ var <value-of select="$nullTransitionFunctionName"/> =
function(){}; //null transition
+
+ //state transition table
+ <call-template name="genStateTransitionTable"/>
+ </template>
+
+ <!-- foreach basicState in set of basic states sorted by stateNum
+ find default (eventless) transitions for that state
+ foreach event in set of events sorted by event id
+ find transition that originates at that state and has
that event -->
+
+ <template name="genStateTransitionTable">
+ <text>var STATE_TRANSITION_TABLE = [ </text>
+
+ <for-each select="$basicStates">
+ <sort select="@c:stateNum" data-type="number"/>
+
+ <variable name="currentState" select="."/>
+
+ <!-- get the default transitions for this state
-->
+
+ <text>[</text>
+
+ <for-each select="$eventsEnum">
+ <sort select="c:id"
data-type="number"/>
+
+ <variable name="currentEvent"
select="."/>
+
+ <variable
name="isDefaultTransition" select="$currentEvent/c:name = '$default'"/>
+
+ <!--get the corresponding
transition-->
+ <!-- conditionally
instantiating this variable to a node-set.
+ hacky syntax, see
http://dpawson.co.uk/xsl/sect2/N8090.html#d10871e1456 -->
+ <variable
name="correspondingTransitions"
select="$currentState/s:transition[$isDefaultTransition][not(@event)] |
$currentState/s:transition[not($isDefaultTransition)]...@event =
$currentEvent/c:name]"/>
+
+ <!--
+ <message>
+ state: <value-of
select="$currentState/@id"/>
+ stateNum: <value-of
select="$currentState/@c:stateNum"/>
+ event: <value-of
select="$currentEvent/c:name"/>
+ eventId: <value-of
select="$currentEvent/c:id"/>
+ transitions to:
<value-of select="$correspondingTransitions/@target"/>
+ </message>
+ -->
+
+ <choose>
+ <when
test="$correspondingTransitions">
+ <for-each
select="$correspondingTransitions">
+
<value-of select="@c:tName"/>
+ </for-each>
+ </when>
+ <otherwise>
+ <value-of
select="$nullTransitionFunctionName"/>
+ </otherwise>
+ </choose>
+
+ <if test="not(position() =
last())">
+ <text>,</text>
+ </if>
+ </for-each>
+ <text>]</text>
+ <if test="not(position() = last())">
+ <text>,
+</text>
+ </if>
+ </for-each>
+ <text>]</text>
+ </template>
+
+</stylesheet>
\ No newline at end of file
Propchange:
commons/sandbox/gsoc/2010/scxml-js/branches/browser-tests.1.ie/src/xslt/backends/js/StateTableStatechartGenerator_combined.xsl
------------------------------------------------------------------------------
svn:eol-style = native
Added:
commons/sandbox/gsoc/2010/scxml-js/branches/browser-tests.1.ie/src/xslt/backends/js/SwitchyardStatechartGenerator_combined.xsl
URL:
http://svn.apache.org/viewvc/commons/sandbox/gsoc/2010/scxml-js/branches/browser-tests.1.ie/src/xslt/backends/js/SwitchyardStatechartGenerator_combined.xsl?rev=956932&view=auto
==============================================================================
---
commons/sandbox/gsoc/2010/scxml-js/branches/browser-tests.1.ie/src/xslt/backends/js/SwitchyardStatechartGenerator_combined.xsl
(added)
+++
commons/sandbox/gsoc/2010/scxml-js/branches/browser-tests.1.ie/src/xslt/backends/js/SwitchyardStatechartGenerator_combined.xsl
Tue Jun 22 15:52:33 2010
@@ -0,0 +1,714 @@
+<?xml version="1.0" encoding="UTF-8"?><!--
+ * 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.
+--><stylesheet xmlns="http://www.w3.org/1999/XSL/Transform"
xmlns:s="http://www.w3.org/2005/07/scxml" xmlns:c="urn://scxml-js"
version="1.0">
+
+ <output method="text"/><param name="log" select="true()"/><param
name="noIndexOf" select="false()"/><param name="noMap" select="false()"/><param
name="noForEach" select="false()"/><param name="name"/><variable
name="allStates" select="//*[(self::s:state or self::s:parallel or
self::s:final or self::s:initial or self::s:scxml or
self::s:history)]"/><variable name="states" select="//s:state"/><variable
name="transitions" select="//s:transition"/><variable name="basicStates"
select="$allStates[not(.//*[(self::s:state or self::s:parallel or self::s:final
or self::s:initial or self::s:scxml or self::s:history)])]"/><variable
name="compositeStates" select="$allStates[.//*[(self::s:state or
self::s:parallel or self::s:final or self::s:initial or self::s:scxml or
self::s:history)]]"/><variable name="eventsEnum"
select="/s:scxml/c:eventsEnum/c:event"/><template match="/s:scxml">
+
+ <if test="$noIndexOf">
+ <call-template
name="genNoIndexOfArrayPrototypeExtension"/>
+ </if>
+
+ <if test="$noMap">
+ <call-template name="genNoMapArrayPrototypeExtension"/>
+ </if>
+
+ <if test="$noForEach">
+ <call-template
name="genNoForEachArrayPrototypeExtension"/>
+ </if>
+
+ function <value-of select="$name"/>StatechartExecutionContext(){
+
+ var self = this; //used in the rare
occasions we call public functions from inside this class
+
+ //abstract state
+
+ <call-template name="genAbstractState">
+ <with-param name="events"
select="$eventsEnum"/>
+ </call-template>
+
+ //states
+ <for-each select="$allStates">
+ <call-template name="genState">
+ <with-param name="state"
select="."/>
+ </call-template>
+ </for-each>
+
+
+ //states enum for glass-box unit testing
+ <call-template name="genStatesEnum">
+ <with-param name="states"
select="$basicStates"/>
+ </call-template>
+
+ //trigger methods for synchronous interaction
+ <for-each select="$eventsEnum">
+ <call-template
name="genExternalTriggerDispatcher">
+ <with-param name="event"
select="."/>
+ </call-template>
+ </for-each>
+
+ <call-template name="genContextHooks"/>
+
+ //initialization script
+ <value-of select="s:script"/>
+
+ //initialization method
+ <call-template name="genInitialization"/>
+
+ //internal runtime functions
+ <call-template
name="genInternalRuntimeFunctions"/>
+
+ //start static boilerplate code
+ <call-template
name="genBoilerplateDispatchCode"/>
+
+ }
+
+ </template><template name="genAbstractState">
+ <param name="events"/>
+
+ var AbstractState = new function(){
+ //triggers are methods
+
+ <for-each select="$events">
+ this.<value-of select="./c:name"/> =
function(){};
+ </for-each>
+
+ this.$default = function(){};
+ }
+ </template><template name="genState">
+ <param name="state"/>
+
+ <variable name="stateName" select="$state/@id"/>
+
+ <variable name="parentName">
+ <choose>
+ <!-- FIXME: probably want to refine this query,
as we may not be able to assume that all states have ids?-->
+ <when test="$state/../@id">
+ <value-of select="$state/../@id"/>
+ </when>
+ <otherwise>
+ <value-of select="'AbstractState'"/>
+ </otherwise>
+ </choose>
+ </variable>
+
+ <variable name="historyState" select="$state/s:history"/>
+
+ <variable name="constructorFunctionName"
select="concat($stateName,'Constructor')"/>
+
+ <!--
+ var stateName = sta...@id;
+ var parentName = state.parent() ?
state.parent()....@id : "AbstractState";
+ var historyState = state.history;
+ var hasHistoryState =
historyState.length() > 0;
+ var constructorFunctionName = stateName
+ "Constructor";
+ -->
+
+ var <value-of select="$stateName"/> = (function(){
+
+ function <value-of
select="$constructorFunctionName"/>(){
+ this.parent = <value-of select="$parentName"/>;
+
+ this.initial = null;
+
+ this.depth = <value-of
select="count($state/ancestor::*)"/>;
+
+ this.historyState = null;
+
+ <if test="$state/self::s:history">
+ this.parent.historyState = this; //init
parent's pointer to history state
+ </if>
+
+ <if test="$state/self::s:initial">
+ this.parent.initial = this; //init
parent's pointer to initial state
+ </if>
+
+ this.toString = function(){
+ return "<value-of select="$stateName"/>"
+ }
+
+ this.enterAction = function(){
+ <if test="$log">
+ console.log("entering <value-of
select="$stateName"/>");
+ </if>
+
+ <apply-templates
select="$state/s:onentry/*[self::s:if or self::s:raise or self::s:log or
self::s:script or self::s:send or self::s:cancel or self::s:invoke or
self::s:finalize or self::s:datamodel or self::s:data or self::s:assign or
self::s:validate or self::s:param]"/>
+ }
+
+ this.exitAction = function(){
+ <if test="$log">
+ console.log("exiting <value-of
select="$stateName"/>" );
+ </if>
+
+ <if test="$historyState">
+
this.historyState.lastConfiguration = currentConfiguration.slice();
+ </if>
+
+ <apply-templates
select="$state/s:onexit/*[self::s:if or self::s:raise or self::s:log or
self::s:script or self::s:send or self::s:cancel or self::s:invoke or
self::s:finalize or self::s:datamodel or self::s:data or self::s:assign or
self::s:validate or self::s:param]"/>
+ }
+
+ <call-template name="genStateHooks">
+ <with-param name="state"
select="$state"/>
+ </call-template>
+
+
+ }
+ <value-of select="$constructorFunctionName"/>.prototype
= <value-of select="$parentName"/>;
+ return new <value-of
select="$constructorFunctionName"/>();
+ })();
+
+ </template><template name="genStatesEnum">
+ <param name="states"/>
+
+ this._states = {
+ <for-each select="$states">
+ <value-of select="@id"/> : <value-of
select="@id"/>
+ <if test="not(position() = last())">,</if>
+ </for-each>
+ }
+
+ </template><template match="s:if">
+ if (<value-of select="@cond"/>) {
+ <apply-templates select="c:executableContent/*"/>
+ }
+ <apply-templates select="s:elseif"/>
+ <apply-templates select="s:else"/>
+ </template><template match="s:elseif">
+ else if (<value-of select="@cond"/>) {
+ <apply-templates select="c:executableContent/*"/>
+ }
+ </template><template match="s:else">
+ else {
+ <apply-templates select="c:executableContent/*"/>
+ }
+ </template><template match="s:log">
+ <if test="@label">
+ console.log( ' <value-of select="@label"/> : ' );
+ </if>
+ <if test="@expr">
+ console.log( <value-of select="@expr"/> );
+
+ </if>
+ </template><template match="s:raise">
+ <!--TODO-->
+ </template><template match="s:script">
+ <value-of select="."/>
+ </template><template match="s:cancel">
+ <!--TODO-->
+ </template><template match="s:invoke">
+ <!--TODO-->
+ </template><template match="s:finalize">
+ <!--TODO-->
+ </template><template match="s:datamodel">
+ <!--TODO-->
+ </template><template match="s:data">
+ <!--TODO-->
+ </template><template match="s:assign">
+ <!--TODO-->
+ </template><template match="s:validate">
+ <!--TODO-->
+ </template><template match="s:param">
+ <!--TODO-->
+ </template><template name="genInternalRuntimeFunctions">
+ function sortByDepthDeepToShallow(a,b){
+ return b.depth - a.depth;
+ }
+ </template><template name="genBoilerplateDispatchCode">
+ //static private member variables
+ var currentConfiguration = []; //current configuration
+ var innerEventQueue = []; //inner event queue
+ var outerEventQueue = []; //outer event queue
+ var isInStableState = true;
+ var isPreempted = false;
+ var hasTakenDefaultTransition = false;
+ var destroyed = false;
+ var mainLoopCallback = null;
+
+ //static private member functions
+ function mainLoop() {
+
+ if(!destroyed){
+ //take an event from the current outer event
queue
+ if (outerEventQueue.length &&
isInStableState) {
+
runToCompletion(outerEventQueue.shift());
+ }
+ //call back
+ mainLoopCallback = window.setTimeout(function()
{
+ mainLoop(); //FIXME: note that when
calling mainloop this way, we won't have access to the "this" object.
+ //I don't think we ever use it though.
Everything we need is private in function scope.
+ },
+ 100);
+ }
+ }
+
+ function runToCompletion(e){
+ isInStableState = false;
+
+ if(e){
+ innerEventQueue.push(e);
+ }
+
+ do{
+ //take any available default transitions
+ microstep(<value-of
select="$defaultEventLiteral"/>);
+
+ if(!hasTakenDefaultTransition){
+
+ if(!innerEventQueue.length){
+ //we have no more generated
events, and no default transitions fired, so
+ //we are done, and have run to
completion
+ break;
+ }else{
+ //microstep, then dequeue next
event sending in event
+
microstep(innerEventQueue.shift());
+ }
+ }else{
+ //he has taken a default transition, so
reset the global variable to false and loop again
+ hasTakenDefaultTransition = false;
+ }
+
+ }while(true)
+
+ isInStableState = true;
+ }
+
+ function microstep(e){
+ currentConfiguration.forEach(function(state){
+ if(!isPreempted)
+ <value-of select="$dispatchInvocation"/>
+ });
+
+ //reset the isPreempted flag
+ isPreempted = false;
+ }
+
+
+ this.destroy = function(){
+ //right now, this only disables timer and sets global
destroyed variable to prevent future callbacks
+ window.clearTimeout(mainLoopCallback);
+ mainLoopCallback = null;
+ destroyed = true;
+ }
+
+
+ //this is for async communication
+ this.GEN = function(e){
+ outerEventQueue.push(e);
+ }
+
+ //this may or may not be something we want to expose, but for
right now, we at least need it for testing
+ this.getCurrentConfiguration = function(){
+ //slice it to return a copy of the configuration rather
than the conf itself
+ //this saves us all kinds of confusion involving
references and stuff
+ return <value-of
select="$currentConfigurationExpression"/>;
+ }
+
+ //end static boilerplate code
+ </template><variable name="deepHistoryEnterAction">
+ <text>
+ var topState;
+ while(topState = statesEntered.pop()){
+ topState.enterAction();
+ }
+ </text>
+ </variable><variable name="shallowHistoryEnterAction">
+ <text>
+ var topState = statesEntered.pop();
+
+ topState.enterAction();
+
+ newConfiguration.push(topState.initial ?
topState.initial : topState );
+ </text>
+ </variable><variable
name="genNonBasicTriggerDispatcherExitBlockInnerForEach">
+ <text>
+ do{
+ statesExited.push(state);
+ }while((state = state.parent) &&
+ state != lca &&
+ statesExited.indexOf(state) == -1)
+ </text>
+ </variable><template name="genHistoryTriggerDispatcher">
+ <param name="s"/>
+ <param name="t"/>
+
+ <variable name="isDeep" select="$s/@type = 'deep'"/>
+ <variable name="historyStateReference">
+ <call-template
name="genHistoryTriggerDispatcherHistoryStateReference">
+ <with-param name="s" select="$s"/>
+ </call-template>
+ </variable>
+
+
+ //history state semantics
+ if(<value-of
select="$historyStateReference"/>.lastConfiguration){
+
+ //transition action
+ <if test="$log">
+ <choose>
+ <when test="$isDeep">
+ console.log("return to last
deep configuration");
+ </when>
+ <otherwise>
+ console.log("return to last
shallow configuration");
+ </otherwise>
+ </choose>
+ </if>
+
+
+ <!--gen executable content for t-->
+ <apply-templates select="$t/*[self::s:if or
self::s:raise or self::s:log or self::s:script or self::s:send or
self::s:cancel or self::s:invoke or self::s:finalize or self::s:datamodel or
self::s:data or self::s:assign or self::s:validate or self::s:param]"/>
+
+
+
+ var historyState = <value-of
select="$historyStateReference"/>;
+
+ <if test="not($isDeep)">
+ var newConfiguration = [];
+ </if>
+
+ <value-of
select="$historyStateReference"/>.lastConfiguration.forEach(function(state){
+ <call-template
name="genHistoryTriggerDispatcherInnerForEach">
+ <with-param name="isDeep"
select="$isDeep"/>
+ </call-template>
+ });
+
+ <choose>
+ <when test="$isDeep">
+ currentConfiguration = <value-of
select="$historyStateReference"/>.lastConfiguration.slice();
+ </when>
+ <otherwise>
+ currentConfiguration = <value-of
select="$genHistoryTriggerDispatcherCurrentConfigurationAssignmentRHS"/>;
+ </otherwise>
+ </choose>
+
+ }else{
+ <call-template name="genTriggerDispatcherContents">
+ <with-param name="s" select="$s"/>
+ <with-param name="t" select="$t"/>
+ </call-template>
+ }
+ </template><template name="genHistoryTriggerDispatcherInnerForEach">
+ <param name="isDeep"/>
+
+ var statesEntered = [<value-of
select="$genHistoryTriggerDispatcherInnerForEachStateReference"/>];
+
+ for(var parent = <value-of
select="$genHistoryTriggerDispatcherInnerForEachStateReference"/>.parent;
+ parent != historyState.parent && parent !=
null;
+ parent = parent.parent){
+ statesEntered.push(parent);
+ }
+
+
+ <choose>
+ <when test="$isDeep">
+ <value-of select="$deepHistoryEnterAction"/>
+ </when>
+ <otherwise>
+ <value-of select="$shallowHistoryEnterAction"/>
+ </otherwise>
+ </choose>
+ </template><template name="genNonBasicTriggerDispatcherExitBlock">
+ <param name="t"/>
+
+ var statesExited = [];
+ var lca = <value-of select="$t/c:lca"/>;
+
+ <value-of
select="$genNonBasicTriggerDispatcherExitBlockIteratorExpression"/>.forEach(function(state){
+ <value-of
select="$genNonBasicTriggerDispatcherExitBlockInnerForEach"/>
+ });
+
+ //sort by depth
+ statesExited.sort(sortByDepthDeepToShallow);
+
+ //execute actions for each of these states
+ statesExited.forEach(function(state){
+ state.exitAction();
+ });
+ </template><template name="genTriggerDispatcherContents">
+ <param name="s"/>
+ <param name="t"/>
+
+ <if test="not($t/@event)">
+ hasTakenDefaultTransition = true;
+ </if>
+
+ //exit states
+ <choose>
+ <when test="local-name($s) = 'initial' or
local-name($s) = 'history' or ( $s/@c:isBasic and (
not($s/@c:isParallelSubstate) or ($s/@c:isParallelSubstate and
not($t/@c:exitsParallelRegion))))">
+ <for-each select="$t/c:exitpath/c:state">
+ <value-of select="."/>.exitAction();
+ </for-each>
+ </when>
+ <otherwise>
+ <call-template
name="genNonBasicTriggerDispatcherExitBlock">
+ <with-param name="t" select="$t"/>
+ </call-template>
+ </otherwise>
+ </choose>
+
+ //transition action
+ <apply-templates select="$t/*[self::s:if or self::s:raise or
self::s:log or self::s:script or self::s:send or self::s:cancel or
self::s:invoke or self::s:finalize or self::s:datamodel or self::s:data or
self::s:assign or self::s:validate or self::s:param]"/>
+
+ //enter states
+ <for-each select="$t/c:targets/c:target/c:enterpath/c:state">
+ <!-- iterate in reverse order -->
+ <sort select="position()" data-type="number"
order="descending"/>
+ <value-of select="."/>.enterAction();
+ </for-each>
+
+ //update configuration
+ <choose>
+ <when test="$s/@c:isParallelSubstate and
not($t/@c:exitsParallelRegion)">
+ <call-template
name="genParallelSubstateConfigurationSetString">
+ <with-param name="s" select="$s"/>
+ <with-param name="t" select="$t"/>
+ </call-template>
+ </when>
+ <otherwise>
+ <call-template
name="genNonParallelSubstateConfigurationSetString">
+ <with-param name="s" select="$s"/>
+ <with-param name="t" select="$t"/>
+ </call-template>
+ </otherwise>
+ </choose>
+
+
+ //set whether preempted
+ <if test="$t/@c:isPreempted">
+ isPreempted = true;
+ </if>
+ </template><template name="genNoForEachArrayPrototypeExtension">
+ if(!Array.forEach){
+ Array.prototype.forEach = function(fn){
+ for(var i=0; i < this.length; i++){
+ fn(this[i]);
+ }
+ return undefined;
+ }
+ }
+ </template><template name="genNoIndexOfArrayPrototypeExtension">
+ if(!Array.indexOf){
+ Array.prototype.indexOf = function(obj){
+ for(var i=0; i < this.length; i++){
+ if(this[i]==obj){
+ return i;
+ }
+ }
+ return -1;
+ }
+ }
+ </template><template name="genNoMapArrayPrototypeExtension">
+ if(!Array.map){
+ Array.prototype.map = function(fn){
+ var toReturn = [];
+ for(var i=0; i < this.length; i++){
+ toReturn[i]=fn(this[i]);
+ }
+ return toReturn;
+ }
+ }
+ </template><param name="defaultEventLiteral"
select="'$default'"/><param name="currentConfigurationExpression"
select="'currentConfiguration.map(function(s){return
STATE_INT_ID_TO_OBJECT_MAP[s]})'"/><param
name="genHistoryTriggerDispatcherCurrentConfigurationAssignmentRHS"
select="'newConfiguration.map(function(sObj){return sObj.id})'"/><param
name="genHistoryTriggerDispatcherInnerForEachStateReference"
select="'STATE_INT_ID_TO_OBJECT_MAP[state]'"/><param
name="genNonBasicTriggerDispatcherExitBlockIteratorExpression"
select="'currentConfiguration.map(function(state){return
STATE_INT_ID_TO_OBJECT_MAP[state]})'"/><template name="genContextHooks">
+ //enumeration of states int id's
+ <for-each select="$basicStates">
+ var <value-of select="@c:enumId"/> = <value-of
select="@c:stateNum - 1"/>;
+ </for-each>
+
+ //map from states int id's to objects
+ var STATE_INT_ID_TO_OBJECT_MAP = [
+ <for-each select="$basicStates">
+ <value-of select="@id"/> <if test="not(position() =
last())"> , </if>
+ </for-each> ];
+
+ //tag each state object with an int id to map from object to id
+ //only needed for history
+ <for-each select="$basicStates">
+ <value-of select="@id"/>.id = <value-of
select="@c:stateNum - 1"/>;
+ </for-each>
+
+ //enumeration of triggers
+ <for-each select="$eventsEnum">
+ var <value-of select="c:name"/> = <value-of
select="c:id"/>;
+ </for-each>
+
+ //expose them as a convenient interface as part of the API
+ <call-template name="genTriggerExternalObject"/>
+
+ //needed for debugging
+ <call-template name="genTriggerIdToNameMap"/>
+
+ //transition functions
+ <for-each select="$transitions">
+ <call-template name="genTriggerDispatcherContext">
+ <with-param name="s" select=".."/>
+ <with-param name="t" select="."/>
+ </call-template>
+ </for-each>
+
+ <call-template name="genEnumeratedHooks"/>
+ </template><template name="genTriggerExternalObject">
+ this.TRIGGERS = {
+ <for-each select="$eventsEnum">
+ <value-of select="c:name"/> : <value-of
select="c:name"/>
+ <if test="not(position() = last())"> ,
</if>
+ </for-each>
+ };
+ </template><template name="genTriggerIdToNameMap">
+ var TRIGGER_ID_TO_NAME_MAP = [
+ <for-each select="$eventsEnum">
+ '<value-of select="c:name"/>'
+ <if test="not(position() = last())"> , </if>
+ </for-each>
+ ];
+ </template><template name="genTriggerDispatcherContext">
+ <param name="s"/>
+ <param name="t"/>
+
+ var <value-of select="$t/@c:tName"/> = function(){
+ <choose>
+ <when test="$s/@c:isHistory">
+ <call-template
name="genHistoryTriggerDispatcher">
+ <with-param name="s"
select="$s"/>
+ <with-param name="t"
select="$t"/>
+ </call-template>
+ </when>
+ <otherwise>
+ <call-template
name="genTriggerDispatcherContents">
+ <with-param name="s"
select="$s"/>
+ <with-param name="t"
select="$t"/>
+ </call-template>
+ </otherwise>
+ </choose>
+ }
+ </template><template name="genExternalTriggerDispatcher">
+ <param name="event"/>
+
+ this.<value-of select="$event/c:name"/> = function(){
+ if(isInStableState){
+ runToCompletion(<value-of
select="$event/c:name"/>);
+ }else{
+ return undefined;
+ }
+ }
+ </template><template
name="genNonParallelSubstateConfigurationSetString">
+ <param name="t"/>
+
+ currentConfiguration = [
+ <for-each select="$t/c:targets/c:target/c:targetState">
+ <variable name="targetStateId" select="."/>
+ <value-of select="$allstat...@id =
$targetStateId]/@c:enumId"/>
+
+ <if test="not(position() = last())"> , </if>
+ </for-each>
+ ];
+ </template><template name="genParallelSubstateConfigurationSetString">
+ <param name="s"/>
+ <param name="t"/>
+
+
currentConfiguration.splice(currentConfiguration.indexOf(<value-of
select="$s/@c:enumId"/>),1,
+ <for-each select="$t/c:targets/c:target/c:targetState">
+ <variable name="targetStateId" select="."/>
+ <value-of select="$allstat...@id =
$targetStateId]/@c:enumId"/>
+
+ <if test="not(position() = last())"> , </if>
+ </for-each>);
+ </template><template name="genInitialization">
+ <!-- we just need to know what the initial state is -->
+ <variable name="initialStateName" select="$allstat...@id =
/s:scxml/s:initial/s:transition/c:targets/c:target/c:targetState]/@c:enumId"/>
+
+ this.initialize = function(){
+ currentConfiguration = [<value-of
select="$initialStateName"/>];
+ runToCompletion();
+ mainLoop();
+ }
+ </template><template match="s:send">
+ <variable name="sendEvent" select="@event"/>
+ <variable name="sendDelay" select="number(@delay)"/>
+
+ <choose>
+ <when test="$sendDelay">
+ //set timeout
+ toReturn = window.setTimeout(function(){
+ self.GEN(<value-of
select="$sendEvent"/>);
+ }, <value-of select="$sendDelay*1000"/>);
+ </when>
+ <otherwise>
+ //just add the event to the outer queue
+ toReturn = innerEventQueue.push(<value-of
select="$sendEvent"/>);
+ </otherwise>
+ </choose>
+ </template><template
name="genHistoryTriggerDispatcherHistoryStateReference">
+ <param name="s"/>
+
+ <value-of select="$s/@id"/>
+ </template><template name="genStateHooks"/><template
name="genTriggerIntEnum"/>
+
+ <param name="dispatchInvocation" select="'dispatch(state,e)'"/>
+
+ <template name="genEnumeratedHooks">
+ //state transition table
+ <call-template name="genSwitchyard">
+ <with-param name="basicStates"
select="$basicStates"/>
+ </call-template>
+ </template>
+
+ <template name="genSwitchyard">
+ <param name="basicStates"/>
+
+ function dispatch(state,e){
+ switch(state) {
+ <for-each select="$basicStates">
+ <call-template name="genStateCase">
+ <with-param name="s"
select="."/>
+ </call-template>
+ </for-each>
+ }
+ }
+
+ </template>
+
+ <template name="genStateCase">
+ <param name="s"/>
+
+ case <value-of select="$s/@c:enumId"/>:
+ switch(e) {
+ <for-each select="$s/s:transition">
+ <call-template name="genEventCase">
+ <with-param name="t"
select="."/>
+ </call-template>
+ </for-each>
+ }
+ break;
+ </template>
+
+ <template name="genEventCase">
+ <param name="t"/>
+
+ <variable name="eventName">
+ <choose>
+ <when test="$t/@event">
+ <value-of select="$t/@event"/>
+ </when>
+ <otherwise>
+ <value-of select="'$default'"/>
+ </otherwise>
+ </choose>
+ </variable>
+
+ case <value-of select="$eventName"/>:
+ <value-of select="$t/@c:tName"/>();
+ break;
+ </template>
+
+</stylesheet>
\ No newline at end of file
Propchange:
commons/sandbox/gsoc/2010/scxml-js/branches/browser-tests.1.ie/src/xslt/backends/js/SwitchyardStatechartGenerator_combined.xsl
------------------------------------------------------------------------------
svn:eol-style = native