UNPKG

mmir-lib

Version:

MMIR (Mobile Multimodal Interaction and Relay) library

260 lines (218 loc) 8.11 kB
//TODO doc define(['mmirf/scion', 'mmirf/scionUtil', 'mmirf/util/deferred'], function( scion, scionUtil, deferred ) { /** * An array containing all states active. * * @type Array * @private * @memberOf mmir.env.statemachine# */ var statesActive = new Array(); /** * Factory function for creating a new (extended) SCION interpreter instance. * * @param {SCION} scion * the SCION module * @param {SCIONUtil} scionUtil * the util/helper for exending the SCION engine * @param {Objcect} instanceContext * * @private * @memberOf mmir.env.statemachine# */ var newInstance = function( scion, scionUtil, instanceContext ) { /** * @type SCIONInterpreter * @memberOf mmir.env.statemachine.create# */ var _interpreter = null; /** * The load function for <code>instanceContext</code> * * @function * @returns {Deferred} a promise that is resolved when the SCION model is loaded * @memberOf mmir.env.statemachine.create# */ var load = function(){ /** * @type String * @memberOf mmir.env.statemachine.engine# */ var _url = this.arguments || this.doc; /** * @type Deferred * @memberOf mmir.env.statemachine.engine# */ var _defer = deferred(); if (typeof _url === 'undefined') { instanceContext._logger.error('URL is missing!'); return; } /** * @type SCION * @memberOf mmir.env.statemachine.engine# */ var self = this; var isNewScionImpl = scion.SCXML? false : true; var loadFunc = isNewScionImpl? 'pathToModel' : 'urlToModel'; /** * Loads the SCXML file and creates the SCION model. * * Resolves the {@link #_defer} promise (or fails it, if an error occurred). * * @param {XMLHTTPRequest} err * if <code>falsey</code>, loading was successful. * Otherwise contains the failed request for loading the SCXML file. * @param {SCIONModel} model * if err is <code>falsey</code>, holds the SCIONModel. * Otherwise empty. * * @function * @memberOf mmir.env.statemachine.engine# */ scion[loadFunc](_url, function urlToModel(err, model) { if (err) { var url = ''; var printError = function(){ console.error('error for SCXML model at ',_url, ': ', (url? 'could not load "' + url + '" ' : ''), (err.statusText? ': ' + err.statusText : ''), err, model ); }; var printErrorFunc = function(){url = this.url; printError();}; if(err.then) err.then(printErrorFunc, printErrorFunc); else printError(); // alert('SCXML is not valid!'); _defer.reject(err); return; } // listener for transitions / state-changes: var listener = { /** * Listener for state changes (ENTRY) in the SCXML model. * * @param {String} stateName * the name of the state that was entered * * @function * @memberOf mmir.env.statemachine.engine.listener# * * @requires instanceContext._logger {@link mmir.tools.Logger} (i.e. the Logger of the DialogEngine/InputEngine) */ onEntry : function(stateName) { statesActive.push(stateName); if (instanceContext._logger.isDebug()) instanceContext._logger.debug('SCXML State Entry: "' + stateName + '"');// debug }, /** * Listener for state changes (EXIT) in the SCXML model. * * @param {String} stateName * the name of the state that was exited * * @function * @memberOf mmir.env.statemachine.engine.listener# * * @requires instanceContext._logger {@link mmir.tools.Logger} (i.e. the Logger of the DialogEngine/InputEngine) */ onExit : function(stateName) { statesActive.pop(); if (instanceContext._logger.isDebug()) instanceContext._logger.debug('SCXML State Exit: "' + stateName + '"');// debug }, /** * Listener for state changes (TRANSITIONS) in the SCXML model. * * @param {String} sourceState * the name of the origin state for the state transition * @param {Array<String>} targetStatesArray * the names of the target states for the state transition * * @function * @memberOf mmir.env.statemachine.engine.listener# * * @requires instanceContext._logger {@link mmir.tools.Logger} (i.e. the Logger of the DialogEngine/InputEngine) */ onTransition : function(sourceState, targetStatesArray) { if (instanceContext._logger.isDebug()) instanceContext._logger.debug('SCXML State Transition: "' + sourceState + '"->"' + targetStatesArray + '"');// debug if (targetStatesArray && targetStatesArray.length > 1) { instanceContext._logger.warn('SCXML State Transition: multiple target states!'); } } }; //HELPER signal initialization: var resolveInit = function(_interpreter){ _interpreter.registerListener(listener); if (self.onload) { var _scion = scionUtil(_interpreter, isNewScionImpl); if(!self.evalScript) self.scion.ignoreScript(); self.onload( _scion, _defer ); } else { _defer.resolve(instanceContext); } } // instantiate the interpreter if(isNewScionImpl){ model.prepare(function(err, fnModel) { if(err) throw err; listener.onError = function(error) { if (instanceContext._logger.isError()){ var stackInfo = error.stack? ', ' + (error.stack.replace? error.stack.replace(error.reason, '') : error.stack) : ''; if(error.data && error.data.tagname){ if(!stackInfo){ stackInfo = ' ['+error.type+': '+error.name+']'; } error = error.data; } instanceContext._logger.error('SCXML ERROR: in <'+error.tagname+'> ('+error.line+':'+error.column+'): ' + error.reason + stackInfo); } } //instantiate the interpreter _interpreter = new scion.scion.Statechart(fnModel); resolveInit(_interpreter); }); } else { _interpreter = new scion.SCXML(model); resolveInit(_interpreter); } });//END: scion.urlToModel(... return _defer; };//END: load = function(){... instanceContext.load = load; instanceContext.onload = null; instanceContext.doc = null; instanceContext.raise = null; return instanceContext; };//END: newInstance(){... //export: /** * Creates a new SCION engine. * * @param {Object} configuration * The configuration object for the SCION engine: * all properties and functions from this object will be attached * to the returned SCION engine (i.e. the <code>context</code> object). * @param {Object} context * The context object: the SCION engine will be attached to this object. * The context object must have a property <code>_logger</code> with the * following attributes (may be empty non-function): * <code>_logger.isDebug() : Boolean</code> (this SHOULD NOT print / show any message) * <code>_logger.debug(String) : void</code> (this SHOULD NOT print / show any message) * <code>_logger.warn(String) : void</code> (this MAY print / show a warning message) * <code>_logger.error(String) : void</code> (this SHOULD print / show an error message) * or use a Logger instance (see /tools/logger.js) that is setup for the module * that calls this function (see e.g. /manager/dialog/dialogManager::init). * @returns {Object} the created SCION engine object * * @public * @memberOf mmir.env.statemachine# */ function createEngine(configuration , context){ var _instance = newInstance( scion, scionUtil , context); for (var key in configuration) { _instance[key] = configuration[key]; } return _instance; }; return createEngine; });