1 
  2 /**
  3  *  @requires jQuery.Deferred
  4  */
  5 
  6 //TODO doc
  7 
  8 define(['scion', 'scionUtil', 'jquery'], function( scion, scionUtil, $ ) {
  9 
 10     /**
 11      * An array containing all states active.
 12      * 
 13      * @type Array
 14      * @private
 15      * @memberOf mmir.env.statemachine#
 16      */
 17     var statesActive = new Array();
 18     
 19     /**
 20      * Factory function for creating a new (extended) SCION interpreter instance.
 21      * 
 22      * @param {SCION} scion
 23      * 			the SCION module
 24      * @param {SCIONUtil} scionUtil
 25      * 			the util/helper for exending the SCION engine
 26      * @param {Objcect} instanceContext
 27      * 
 28      * @private
 29      * @memberOf mmir.env.statemachine#
 30      */
 31     var newInstance = function( scion, scionUtil, instanceContext ) {
 32     	
 33     	/**
 34     	 * @type SCIONInterpreter
 35     	 * @memberOf mmir.env.statemachine.create#
 36     	 */
 37         var _interpreter = null;
 38 
 39         /**
 40          * The load function for <code>instanceContext</code>
 41          * 
 42          * @function
 43          * @returns {Deferred} a promise that is resolved when the SCION model is loaded
 44     	 * @memberOf mmir.env.statemachine.create#
 45     	 */
 46         var load = function(){
 47         	/**
 48              * @type String
 49         	 * @memberOf mmir.env.statemachine.engine#
 50         	 */
 51             var _url = this.arguments || this.doc;
 52             /**
 53              * @type Deferred
 54         	 * @memberOf mmir.env.statemachine.engine#
 55         	 */
 56             var _defer = $.Deferred();
 57             
 58             if (typeof _url === 'undefined') {
 59             	instanceContext._log.error('URL is missing!');
 60                 return;
 61             }
 62             /**
 63              * @type SCION 
 64         	 * @memberOf mmir.env.statemachine.engine#
 65         	 */
 66             var self = this;
 67             
 68             /**
 69              * Loads the SCXML file and creates the SCION model.
 70              * 
 71              * Resolves the {@link #_defer} promise (or fails it, if an error occurred).
 72              * 
 73              * @param {XMLHTTPRequest} err
 74              * 			if <code>falsey</code>, loading was successful.
 75              * 			Otherwise contains the failed request for loading the SCXML file.
 76              * @param {SCIONModel} model
 77              * 			if err is <code>falsey</code>, holds the SCIONModel.
 78              * 			Otherwise empty.
 79              * 
 80              * @function
 81         	 * @memberOf mmir.env.statemachine.engine#
 82         	 */
 83             scion.urlToModel(_url, function urlToModel(err, model) {
 84 
 85                 if (err) {
 86                 	
 87                 	var url = '';
 88                 	var printError = function(){
 89                 		console.error('error for SCXML model at ',_url, ': ',
 90                 				(url? 'could not load "' + url + '" ' : ''),
 91                 				(err.statusText? ': ' + err.statusText : ''),
 92                 				err,
 93                 				model
 94                 		);
 95                 	};
 96                 	if(err.always) err.always(function(){url = this.url; printError();});
 97                 	else printError();
 98                 	
 99 //                    alert('SCXML is not valid!');
100                 	_defer.fail(err);
101                     return;
102                 }
103 
104                 // instantiate the interpreter
105                 _interpreter = new scion.SCXML(model);
106 
107                 // listener for transitions / state-changes:
108                 var listener = {
109             		/**
110                      * Listener for state changes (ENTRY) in the SCXML model.
111                      * 
112                      * @param {String} stateName
113                      * 			the name of the state that was entered 
114                      * 
115                      * @function
116                 	 * @memberOf mmir.env.statemachine.engine.listener#
117                 	 * 
118                 	 * @requires instanceContext._log {@link Logger} (i.e. the Logger of the DialogEngine/InputEngine)
119                 	 */
120                     onEntry : function(stateName) {
121                         statesActive.push(stateName);
122                         if (instanceContext._log.isDebug()) instanceContext._log.debug('SCXML State Entry: "' + stateName + '"');// debug
123                     },
124                     /**
125                      * Listener for state changes (EXIT) in the SCXML model.
126                      * 
127                      * @param {String} stateName
128                      * 			the name of the state that was exited 
129                      * 
130                      * @function
131                 	 * @memberOf mmir.env.statemachine.engine.listener#
132                 	 * 
133                 	 * @requires instanceContext._log {@link Logger} (i.e. the Logger of the DialogEngine/InputEngine)
134                 	 */
135                     onExit : function(stateName) {
136                         statesActive.pop();
137 
138                         if (instanceContext._log.isDebug()) instanceContext._log.debug('SCXML State Exit: "' + stateName + '"');// debug
139                     },
140                     /**
141                      * Listener for state changes (TRANSITIONS) in the SCXML model.
142                      * 
143                      * @param {String} sourceState
144                      * 			the name of the origin state for the state transition
145                      * @param {Array<String>} targetStatesArray
146                      * 			the names of the target states for the state transition
147                      * 
148                      * @function
149                 	 * @memberOf mmir.env.statemachine.engine.listener#
150                 	 * 
151                 	 * @requires instanceContext._log {@link Logger} (i.e. the Logger of the DialogEngine/InputEngine)
152                 	 */
153                     onTransition : function(sourceState, targetStatesArray) {
154                         
155                     	if (instanceContext._log.isDebug()) instanceContext._log.debug('SCXML State Transition: "' + sourceState + '"->"' + targetStatesArray + '"');// debug
156 
157                         if (targetStatesArray && targetStatesArray.length > 1) {
158                         	instanceContext._log.warn('SCXML State Transition: multiple target states!');
159                         }
160                     }
161                 };
162 
163                 _interpreter.registerListener(listener);
164 
165                 if (self.onload) {
166                 	var _scion = scionUtil( _interpreter );
167                 	if(!self.evalScript) self.scion.ignoreScript();
168                 	self.onload( _scion, _defer );
169                 } else {
170                 	deferred.resolve(instanceContext);
171                 }
172                 
173             });//END: scion.urlToModel(...
174 
175             
176             return _defer.promise();
177             
178         };//END: load = function(){...
179 
180         /**
181     	 * @deprecated instead use the object directly
182     	 */
183         instanceContext.getInstance= function () {
184         	return this;
185         };
186         instanceContext.load = load;
187         instanceContext.onload = null;
188         instanceContext.doc = null;
189         instanceContext.raise = null;
190         
191         return instanceContext;
192         
193     };//END: newInstance(){...
194 
195     
196     //export:
197     
198     /**
199      * Creates a new SCION engine.
200      * 
201      * @param {Object} configuration
202      * 				The configuration object for the SCION engine:
203      * 				all properties and functions from this object will be attached
204      * 				to the returned SCION engine (i.e. the <code>context</code> object).
205      * @param {Object} context
206      * 				The context object: the SCION engine will be attached to this object.
207      * 				The context object must have a property <code>_log</code> with the
208      * 				following attributes (may be empty non-function):
209      * 				<code>_log.isDebug() : Boolean</code>  (this SHOULD NOT print / show any message)
210      * 				<code>_log.debug(String) : void</code> (this SHOULD NOT print / show any message)
211      * 				<code>_log.warn(String) : void</code>  (this MAY print / show a warning message)
212      * 				<code>_log.error(String) : void</code> (this SHOULD print / show an error message)
213      * 				or use a Logger instance (see /tools/logger.js) that is setup for the module
214      * 				that calls this function (see e.g. /manager/dialog/dialogManager::init).
215      * @returns {Object} the created SCION engine object
216      * 
217      * @public
218      * @memberOf mmir.env.statemachine#
219      */
220 	function createEngine(configuration , context){
221 		
222         var _instance = newInstance( scion, scionUtil , context);
223         
224         for (var key in configuration) {
225             _instance[key] = configuration[key];
226         }
227         
228         return _instance;
229                     
230 	};
231 	return createEngine;
232 
233 });
234