1 /*
  2  * 	Copyright (C) 2012-2013 DFKI GmbH
  3  * 	Deutsches Forschungszentrum fuer Kuenstliche Intelligenz
  4  * 	German Research Center for Artificial Intelligence
  5  * 	http://www.dfki.de
  6  * 
  7  * 	Permission is hereby granted, free of charge, to any person obtaining a 
  8  * 	copy of this software and associated documentation files (the 
  9  * 	"Software"), to deal in the Software without restriction, including 
 10  * 	without limitation the rights to use, copy, modify, merge, publish, 
 11  * 	distribute, sublicense, and/or sell copies of the Software, and to 
 12  * 	permit persons to whom the Software is furnished to do so, subject to 
 13  * 	the following conditions:
 14  * 
 15  * 	The above copyright notice and this permission notice shall be included 
 16  * 	in all copies or substantial portions of the Software.
 17  * 
 18  * 	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
 19  * 	OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
 20  * 	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
 21  * 	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
 22  * 	CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
 23  * 	TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
 24  * 	SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 25  */
 26 
 27 define(['core', 'env', 'envInit', 'jquery', 'constants', 'commonUtils', 'configurationManager', 'languageManager'
 28      , 'controllerManager', 'modelManager'
 29      , 'presentationManager', 'inputManager', 'dialogManager', 'module'
 30      , 'semanticInterpreter', 'mediaManager', 'notificationManager'
 31   ],
 32   /**
 33    * Initializes the MMIR framework:
 34    * triggers {@link mmir.ready} when initialization has finished.
 35    * 
 36    * If run with env-setting <code>cordova</code> the initialization starts
 37    * when the <code>deviceready</code> event is fired.
 38    * Otherwise initialization starts when the <code>domready</code> event was fired
 39    * (using jQuery's ready function). 
 40    * 
 41    * @class
 42    * @name main
 43    * @memberof mmir
 44    * @private
 45    * 
 46    * @requires jQuery.Deferred
 47    * 
 48    * @requires jQuery#selector	(for initial CSS/script injections; TODO change mechanism)
 49    * @requires jQuery.is			(for initial script injections; TODO change mechanism)
 50    * @requires jQuery.append		(for initial CSS injections; TODO change mechanism)
 51    * 
 52    */
 53   function(mmir, env, envInit, $, constants, commonUtils, configurationManager, languageManager
 54 	 , controllerManager, modelManager
 55      , presentationManager, inputManager, dialogManager, module
 56      , semanticInterpreter, mediaManager, notificationManager
 57 ){
 58 	//export framework functions/objects
 59 	mmir.Constants = constants;
 60 	mmir.CommonUtils = commonUtils;
 61 	mmir.ConfigurationManager = configurationManager;
 62 	mmir.NotificationManager = notificationManager.init();
 63 	
 64 	var mainInit = function(){
 65 
 66 		console.log('dom ready');
 67     	
 68 		//initialize the common-utils:
 69 		commonUtils.init()//<- load directory structure
 70 			
 71 			//load plugins (if in CORDOVA environment)
 72 			.then(function() {
 73 
 74 				mmir.LanguageManager = languageManager.init();
 75 				
 76 				var defer = $.Deferred();
 77 		        
 78 				//if in Cordova env:
 79 				// * load cordova library
 80 				// * then load the (Cordova) plugins
 81 				// -> after this: continue (i.e. resolve promise)
 82 				var isCordova = env.isCordovaEnv;
 83 				if(isCordova){
 84 //					require(['cordova'], function(){
 85 						commonUtils.loadAllCordovaPlugins()
 86 							.then(defer.resolve());
 87 //					});
 88 		        }
 89 		        else {
 90 		        	// otherwise (e.g. BROWSER env):
 91 		        	// just continue by resolving the promise immediately
 92 		        	defer.resolve();
 93 		        }
 94 
 95 	        	return defer.promise();
 96 			})
 97 			// start the ControllerManager
 98 			.then(function() {
 99 				
100 				mmir.ControllerManager = controllerManager;
101 				
102 				//NOTE: this also gathers information on which 
103 				//      views, layouts etc. are available
104 				//      -> the presentationManager depends on this information
105 				return controllerManager.init();
106 			})
107 			
108 			//TEST parallelized loading of independent modules:
109 			.then(function(){
110 				
111 				var isMediaManagerLoaded 	= false;
112 				var isModelsLoaded 			= false;
113 				var isVisualsLoaded 		= false;
114 				var isInputManagerLoaded 	= false;
115 				var isDialogManagerLoaded 	= false;
116 				var isSemanticsLoaded        = false;
117 				
118 				var checkInitCompleted = function(){
119 					
120 					if(			isMediaManagerLoaded
121 							&&	isModelsLoaded
122 							&& 	isVisualsLoaded 
123 							&&	isInputManagerLoaded
124 							&&	isDialogManagerLoaded
125 							&&	isSemanticsLoaded
126 					){
127 						//get additional configuration for requirejs
128 						//from configuration.json:
129 						// -> if property "config" is set, apply it as requirejs-config
130 						//    before signaling READY
131 						// EXAMPLE:
132 						// the following entry (in config/configuration.json) would add
133 						// the dependency information for www/appjs/test.js as module "testConf"
134 						// 
135 						//	, "config": {
136 						//    	"paths": {
137 						//    		"testConf": "../appjs/test"
138 						//    	}
139 						//    }
140 						//
141 						var requireConfig = configurationManager.get('config');
142 						if(requireConfig){
143 							require.config(requireConfig);
144 						}
145 						
146 						//"give signal" that the framework is now initialized / ready
147 						mmir.setInitialized();
148 					}
149 				};
150 				
151 				mmir.SemanticInterpreter = semanticInterpreter;
152 				var grammarEngine = configurationManager.get('grammarCompiler', true);
153 				if(grammarEngine){
154 					semanticInterpreter.setGrammarEngine(grammarEngine);
155 				}
156 				var grammarCompileMode = configurationManager.get('grammarAsyncCompileMode', true);
157 				if(typeof grammarCompileMode !== 'undefined'){
158 					semanticInterpreter.setEngineCompileMode(grammarCompileMode);
159 				}
160 				
161 				//TODO impl. automated sync/async loading&execution for compiled grammars
162 //				var grammarExecMode = configurationManager.get('grammarExecMode', true);
163 //				if(typeof grammarExecMode !== 'undefined'){
164 //					semanticInterpreter.setGrammarExecMode(grammarExecMode);//TODO add async-loaded grammars to ignoreGrammarFiles-list (to prevent loading them in "sync-exec mode")
165 //				}
166 				
167 				//list of grammar IDs which should not be loaded, even if there is a compiled grammar available:
168 				var ignoreGrammarIds = configurationManager.get('ignoreGrammarFiles', true, void(0));
169 
170 				commonUtils.loadCompiledGrammars(constants.getGeneratedGrammarsPath(), void(0), ignoreGrammarIds).then(function() {
171 					
172 					isSemanticsLoaded = true;
173 					checkInitCompleted();
174 				});
175 
176 				// start the MediaManager
177 				mediaManager.init().then(function() {
178 					isMediaManagerLoaded = true;
179 					
180 					//initialize BEEP notification (after MediaManager was initialized)
181 					notificationManager.initBeep();
182 					
183 					mmir.MediaManager = mediaManager;
184 					checkInitCompleted();
185 				});
186 				
187 				//TODO models may access views etc. during their initialization
188 				//	   --> there should be a way to configure startup, so that models may only be loaded, after everything else was loaded
189 				modelManager.init().then(function(){
190 					isModelsLoaded = true;
191 					mmir.ModelManager = modelManager;
192 					checkInitCompleted();
193 				});
194 				
195 				presentationManager.init().then(function(){
196 					
197 					//FIXME impl. mechanism where this is done for each view/layout rendering 
198 					//   (i.e. in presentationManager's rendering function and not here)
199 					//
200 					//initialize with default layout contents:
201 					var headerContents = $( presentationManager.getLayout(null, true).getHeaderContents() );
202 					//NOTE: need to handle scripts separately, since some browsers may refuse to "simply append" script TAGs...
203 					var scriptList = [];
204 					var stylesheetList = headerContents.filter(function(index){
205 						var tis = $(this);
206 						if( tis.is('script') ){
207 							scriptList.push(tis.attr('src'));
208 							return false;
209 						}
210 						return true;
211 					});
212 					$("head").append( stylesheetList );
213 					commonUtils.loadImpl(scriptList, true)//load serially, since scripts may depend on each other; TODO should processing wait, until these scripts have been finished! (i.e. add callbacks etc.?)
214 							
215 						.then(function(){//<- need to wait until all referenced scripts form LAYOUT have been loaded (may be used/required when views get rendered)
216 
217 								isVisualsLoaded = true;//<- set to "LOADED" after all scripts have been loaded / TODO impl. better mechanism for including application-scripts...
218 					
219 								mmir.PresentationManager = presentationManager;
220 								checkInitCompleted();
221 					});
222 				});
223 				//TODO handle reject/fail of the presentationManager's init-Promise!
224 				
225 				dialogManager.init().then(function(_dlgMng, _dialogEngine){
226 					isDialogManagerLoaded = true;
227 					mmir.DialogManager = dialogManager;
228 					mmir.DialogEngine = _dialogEngine;
229 					checkInitCompleted();
230 				});
231 				
232 				inputManager.init().then(function(_inputMng, _inputEngine){
233 					isInputManagerLoaded = true;
234 					mmir.InputManager = inputManager;
235 					mmir.InputEngine  = _inputEngine; 
236 					checkInitCompleted();
237 				});
238 				
239 				
240 				
241 			});
242 			
243 
244 	};//END: mainInit(){...
245 	
246 	//TEST for reference/testing: strictly serial initialization of the modules/managers:
247 //	var mainSerialInit = function(){
248 //
249 //		console.log('dom ready');
250 //    	
251 //		//load plugins
252 //		commonUtils.init()//<- load directory structure
253 //			
254 //			//load compiled grammars (if present)
255 //			.then(function() {
256 //
257 //				mmir.SemanticInterpreter = semanticInterpreter;
258 //				return commonUtils.loadCompiledGrammars(constants.getGeneratedGrammarsPath());//TODO remove dependency on constants-obj here (move into commonUtils? and/or make param optional?)
259 //			})
260 //			
261 //			//load plugins (if in CORDOVA environment)
262 //			.then(function() {
263 //
264 //				mmir.LanguageManager = languageManager.init();
265 //				
266 //				var defer = $.Deferred();
267 //		        
268 //				//if in Cordova env:
269 //				// * load cordova library
270 //				// * then load the (Cordova) plugins
271 //				// -> after this: continue (i.e. resolve promise)
272 //				var isCordova = env.isCordovaEnv;
273 //				if(isCordova){
274 //					require(['cordova'], function(){
275 //						commonUtils.loadAllCordovaPlugins()
276 //							.then(defer.resolve());
277 //					});
278 //		        }
279 //		        else {
280 //		        	// otherwise (e.g. BROWSER env):
281 //		        	// just continue by resolving the promise immediately
282 //		        	defer.resolve();
283 //		        }
284 //
285 //	        	return defer.promise();
286 //			})
287 //			// start the MediaManager
288 //			.then(function() {
289 //				
290 //				mmir.MediaManager = mediaManager;
291 //				return mediaManager.init();
292 //			})
293 //			// start the ControllerManager
294 //			.then(function() {
295 //
296 //				notificationManager.initBeep();//initialize BEEP notification (after MediaManager was initialized)
297 //				
298 //				mmir.ControllerManager = controllerManager;
299 //				return controllerManager.init();
300 //			})
301 //	
302 //			// start the ModelManager
303 //			.then(function() {
304 //				
305 //				//TODO models may access views etc. during their initialization
306 //				//	   --> there should be a way to configure startup, so that models may only be loaded, after everything else was loaded
307 //				return modelManager.init();
308 //			})
309 //	
310 //			// start the PresentationManager
311 //			.then(function() {
312 //				
313 //				return presentationManager.init();
314 //			})
315 //	
316 //			// start the InputManager
317 //			.then(function() {
318 //				
319 //				//FIXME this should be done on rendering (and (possibly) removing obsolete the CSS header contents)
320 //				$("head").append(presentationManager.getLayout("Application").getHeaderContents());
321 //				
322 //				mmir.InputManager = inputManager;
323 //				return mmir.InputManager.init();
324 //			})
325 //	
326 //			// start the DialogManager
327 //			.then(function() {
328 //				mmir.DialogManager = dialogManager;
329 //				return mmir.DialogManager.init();
330 //			})
331 //	
332 //			// start the app
333 //			.then(function(_engine) {
334 //				
335 //				//"give signal" that the framework is now initialized / ready
336 //				mmir.setInitialized();
337 //	
338 //			});
339 //			
340 //
341 //	};//END: mainSerialInit(){...
342 //	
343 //	mainInit = mainSerialInit;
344 	
345 	if(env.isCordovaEnv){
346 		
347 		document.addEventListener("deviceready", mainInit, false);
348 	}
349 	else {
350 		
351 		$(mainInit);
352 	}
353 	//END: $(function() {...
354 
355 	
356 });//END: define(...
357