1 
  2 /**
  3  * loads the default grammar asynchronously using a WebWorker
  4  * 
  5  * NOTE usage of the grammar is also async:
  6  *      calls on getASRSemantic(text, callback) are re-directed to the WebWorker
  7  * 
  8  */
  9 define(['constants', 'commonUtils', 'semanticInterpreter', 'jquery'], function(constants, utils, semanticInterpreter, $){
 10 
 11 //
 12 var _pendingCmds = {};
 13 var _cmdIdCounter = 1;
 14 
 15 var _loadedGrammars = {};
 16 
 17 //web-worker instance:
 18 var _asyncGrammarLoader = new Worker(constants.getWorkerPath()+'asyncGrammarWorker.js');
 19 
 20 //process messages from worker thread:
 21 _asyncGrammarLoader.onmessage = function(msg){
 22 	
 23 	var data = msg.data;
 24 	var cmd = data.cmd;
 25 	if(cmd){
 26 		
 27 		if(cmd === 'stopwords'){
 28 			
 29 			semanticInterpreter.setStopwords(data.id, data.stopwords);
 30 			
 31 			//check/trigger init-listener
 32 			if(typeof _loadedGrammars[data.id] === 'object'){
 33 				_loadedGrammars[data.id].isStopwords = true;
 34 				_loadedGrammars[data.id].checkInit();
 35 			}
 36 			
 37 		} else if(cmd === 'setgrammar'){
 38 			
 39 			//replace the default impl. of the grammar execution:
 40 			//  re-direct invocations to the worker thread and 
 41 			//  return the results via the callback
 42 			var execGrammar = function(text, callback){
 43 				
 44 				var cmdid = ''+ _cmdIdCounter++;
 45 				
 46 				this.executeGrammar._pendingCmds[cmdid] = callback;
 47 				
 48 				var langid = this.executeGrammar._langCode;
 49 				
 50 				_asyncGrammarLoader.postMessage({cmd: 'parse', id: langid, cmdId: cmdid, text: text});
 51 			};
 52 			
 53 			execGrammar._pendingCmds = _pendingCmds;
 54 			execGrammar._langCode = data.id;
 55 			
 56 			var options = data.options;
 57 			if(options.execMode != 'async'){
 58 				options.execMode = 'async';
 59 			}
 60 			semanticInterpreter.addGrammar(data.id,execGrammar,options);
 61 			
 62 			//check/trigger init-listener
 63 			if(typeof _loadedGrammars[data.id] === 'object'){
 64 				_loadedGrammars[data.id].isGrammar = true;
 65 				_loadedGrammars[data.id].checkInit();
 66 			}
 67 			
 68 		} else if(cmd === 'parseresult'){
 69 			
 70 			var cmdid = data.cmdId;
 71 			
 72 			if(!_pendingCmds[cmdid]){
 73 				console.error('no callback registered for cmd-ID '+cmdid+', ignoring result '+JSON.stringify(cmd.result));
 74 				return;////////////////// EARLY EXIT /////////////////////////////////
 75 			}
 76 			
 77 			_pendingCmds[cmdid].call(semanticInterpreter, data.result);
 78 			_pendingCmds[cmdid] = void(0);
 79 			
 80 		} else if(cmd === 'error'){
 81 			
 82 			console.error('encountered error: '+JSON.stringify(data));
 83 			
 84 		} else {
 85 			
 86 			console.error('unknown response from loader: '+JSON.stringify(msg.data));
 87 		}
 88 		
 89 	} else {
 90 		
 91 		console.error('unknown response from loade: '+JSON.stringify(msg.data));
 92 	}
 93 	
 94 };
 95 
 96 
 97 return {
 98 	
 99 	/**
100 	 * Initialize a grammar to be loaded & executed asynchronously
101 	 * 
102 	 * After
103 	 * 
104 	 * @requires WebWorker
105 	 */
106 	init: function(langCode, listener, phrase){
107 		
108 		//use default language, if none is specified
109 		if(!langCode){
110 			langCode = semanticInterpreter.getCurrentGrammar();
111 		}
112 		
113 		if(!langCode){
114 			console.error('Inavlid grammar ID: "'+langCode+'"');
115 			return false;//////////////////// EARLY EXIT////////////////////////
116 		}
117 		
118 		//if grammar is already loaded & available:
119 		if(_loadedGrammars[langCode] === true){
120 			semanticInterpreter.getASRSemantic(phrase, langCode, listener);
121 			return true;//////////////////// EARLY EXIT ////////////////////////
122 		}
123 		
124 		utils.init().then(function onSuccess(){
125 			
126 				var compiledGrammarPath = utils.getCompiledGrammarPath(constants.getGeneratedGrammarsPath(), langCode);
127 				if(!compiledGrammarPath){
128 					console.error('No compiled grammar available for ID: "'+langCode+'"');
129 					return;//////////////////// EARLY EXIT////////////////////////
130 				}
131 				
132 				var grammarInit = {
133 					id: langCode,
134 					initDef: $.Deferred(),
135 					isGrammar: false,
136 					isStopwords: false,
137 					checkInit: function(){
138 						if(this.isStopwords && this.isGrammar){
139 							_loadedGrammars[this.id] = true;
140 							this.initDef.resolve();
141 							this.initDef = null;
142 						}
143 					}
144 				};
145 	
146 				//register invocation of init-phrase as soon as (async-loaded) grammar becomes available
147 				grammarInit.initDef.always(function(){
148 					
149 					if(typeof phrase !== 'undefined'){
150 						semanticInterpreter.getASRSemantic(phrase, langCode, listener);
151 					} else {//TODO use grammar's example_phrase for init instead?
152 						listener({});
153 					}
154 					
155 				});
156 				_loadedGrammars[langCode] = grammarInit;
157 
158 				_asyncGrammarLoader.postMessage({cmd: 'load', id: langCode, url: compiledGrammarPath});
159 			},
160 			function onError(){
161 				
162 				//FIXME impl. real error handling
163 				console.error('cannot determine URL for compiled grammar with ID "'+langCode+'": commonUtils is not initialized.');
164 		});
165 		
166 		return true;
167 	}
168 };
169 
170 });
171