1 /*
  2  * 	Copyright (C) 2012-2015 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 
 28 
 29 define(['dictionary', 'stacktrace', 'module'], 
 30 /**
 31  * A Logger factory.<br>
 32  * 
 33  * @example 
 34  *  //use logger
 35  *  var Logger = require('logger');
 36  *  var log = Logger.create('example');
 37  *  
 38  *  if(log.isVerbose()) log.debug('test');//will write the message to debug-console)
 39  *  log.error(new Error());//will write the error (including its stack) to error console)
 40  *  
 41  *  //example for setting up a logger in a requirejs-module:
 42  *  define(['logger', 'module'], function(Logger, module){
 43  *  
 44  *    var logger = Logger.create(module);
 45  *    //this would create the same logger-object:
 46  *    //  Logger.create(module.id, module.config().logLevel);
 47  *    
 48  *    //use the logger instance...
 49  *    
 50  *    //create / retrieve the same logger
 51  *    var sameLogger = Logger.create(module.id);
 52  *    
 53  *  });
 54  *  
 55  * @class
 56  * @name Logging
 57  * @memberOf mmir
 58  * @static
 59  * 
 60  * @see Logger
 61  * 
 62  */	
 63 function(Dictionary, stacktrace, module){
 64 
 65 	
 66 var _loggers = new Dictionary();
 67 //var logLevels = new Dictionary();
 68 
 69 /**
 70  * the (global) logging level
 71  * 
 72  * 0: verbose
 73  * 1: debug
 74  * 2: info
 75  * 3: warn
 76  * 4: error
 77  * 5: critical
 78  * 6: disabled
 79  * 
 80  * @memberOf mmir.Logging#
 81  */
 82 var _level = 1;
 83 
 84 /**
 85  * @private
 86  * @type String
 87  * @memberOf mmir.Logging#
 88  */
 89 var tmpLogLevel = module.config().logLevel;
 90 if(typeof tmpLogLevel !== 'undefined'){
 91 	if(typeof tmpLogLevel !== 'number'){
 92 		tmpLogLevel = getAsLevel(tmpLogLevel);
 93 	}
 94 	_level = tmpLogLevel;
 95 }
 96 
 97 
 98 //	//TODO extend / implement helpers for writing CSV file data
 99 //	var csvHeader = [
100 //	    'User name', 'Time', 'Modality', 'Recognized speech', 'Event name', 'Event data', 'Dialog state'
101 //	];
102 //	
103 //	function getCsvLine(){
104 //		return new Array(csvHeader.length);
105 //	}
106 
107 /**
108  * Get the log-level as number.
109  * 
110  * @param {String} strLogLevel
111  * 			the string representation for the log-level
112  * @returns {Number}
113  * 				the log-level as number
114  * @private
115  * @memberOf Logger.prototype
116  * 
117  * @see #getLevel
118  */
119 function getAsLevel(strLogLevel){
120 	if(typeof strLogLevel === 'string'){
121 		var str = strLogLevel.toLowerCase();
122 		if(str === 'verbose'){
123 			return 0;
124 		} else if(str === 'debug'){
125 			return 1;
126 		} else if(str === 'info'){
127 			return 2;
128 		} else if(str === 'warn'){
129 			return 3;
130 		} else if(str === 'error'){
131 			return 4;
132 		} else if(str === 'critical'){
133 			return 5;
134 		} else if(str === 'disabled'){
135 			return 6;
136 		} else
137 			throw new Error('Logger.getAsLevel: unknown parameter value "'+strLogLevel+'"');
138 	}
139 	
140 	throw new TypeError('Logger.getAsLevel: parameter must be number or string, but "'+strLogLevel+'" is '+typeof strLogLevel);
141 }
142 
143 /**
144  * print log message with error information.
145  * 
146  * @private
147  * @memberOf Logger.prototype
148  */
149 function printe(loggerName, logLevel, className, funcName, msg, error){
150 	
151 	if( isErr(className)){
152 		error = className;
153 		className = '';
154 	} else if( isErr(funcName) ){
155 		error = funcName;
156 		funcName = void(0);
157 		if(typeof className === 'undefined'){
158 			className = '';
159 		}
160 	} else if( isErr(msg) ){
161 		error = msg;
162 		msg = void(0);
163 		if(typeof className === 'undefined'){
164 			if(typeof funcName === 'undefined'){
165 				className = '';
166 			}
167 			else {
168 				className = funcName;
169 				funcName = void(0);
170 			}
171 		}
172 	}
173 	
174 	print(loggerName, logLevel, createErr(createMsg(className, funcName, msg), error), true);
175 }
176 
177 /**
178  * creates the message text.
179  * 
180  * @returns {string} the message text
181  * 
182  * @private
183  * @memberOf Logger.prototype
184  */
185 function createMsg(className, funcName, msg){
186 	
187 	var out;
188 	
189 	if(className){
190 		if(funcName){
191 			if(msg){
192 				out = className+'.'+funcName+': '+msg;
193 			} else {
194 				
195 //					if(arguments.callee !== 'undefined'){
196 //						out('callee: '+arguments.callee());
197 //					}
198 				
199 				out = className+': '+funcName;
200 			}
201 		} else {
202 			
203 //				if(arguments.callee !== 'undefined'){
204 //					out('callee: '+arguments.callee());
205 //				}
206 			
207 			out = className;
208 		}
209 	} else {
210 
211 //			if(arguments.callee !== 'undefined'){
212 //				out('callee: '+arguments.callee());
213 //			}
214 		
215 		if(typeof className === 'undefined'){
216 			out = 'UNDEFINED';
217 		} else if(typeof className !== 'string'){
218 			out = Object.prototype.toString.call(null, className);
219 		} else {
220 			out = className;
221 		}
222 	}
223 	
224 	return out;
225 }
226 
227 /**
228  * HELPER: check if errObj is an Error
229  * 
230  * @returns {Boolean}
231  * 
232  * @private
233  * @memberOf Logger.prototype
234  */
235 function isErr(errObj){
236 	
237 	//TODO also do feature detection for error-like objects?
238 	return errObj instanceof Error;
239 }
240 
241 /**
242  * Creates error message (with stack trace, if possible).
243  * 
244  * @returns {string} the error message
245  * 
246  * @private
247  * @memberOf Logger.prototype
248  */
249 function createErr(msg, error){
250 	
251 	var err ='';
252 	var errMsg = '';
253 	var re;
254 	if(error){
255 		
256 		if(error.name){
257 			err = '<'+error.name+'> ';
258 		}
259 		
260 		if(error.number){
261 			err += '#'+error.number+' ';
262 		}
263 		
264 		if(error.stack){
265 			
266 			errMsg = error.stack;
267 			
268 			if(error.name && (re = new RegExp('^'+error.name)).test(errMsg)){
269 				errMsg = errMsg.replace(re, '');
270 			}
271 			
272 		} else {
273 
274 			if(error.message){
275 				errMsg = ' - ' + error.message;
276 			}
277 			
278 			if(error.description){
279 				errMsg = ' - ' + error.description;
280 			}
281 			
282 			if(error.fileName){
283 				
284 				var lineNo = '';
285 				
286 				if(error.lineNumber){
287 					lineNo = ', line ' + error.lineNumber;
288 				}
289 				
290 				errorMsg += ' ('+error.fileName+lineNo+')'; 
291 			}
292 		}
293 		
294 	}
295 	
296 	return err+msg+errMsg;
297 }
298 /**
299  * @private
300  * @memberOf Logger.prototype
301  */
302 function print(loggerName, logLevel, msg){
303 	var prefix, func;
304 	switch(logLevel){
305 	case 0:
306 		prefix = '[VERBOSE] ';
307 		func = 'log';
308 		break;
309 	case 1:
310 		prefix = '[DEBUG] ';
311 		func = 'debug';
312 		break;
313 	case 2:
314 		prefix = '[INFO] ';
315 		func = 'info';
316 		break;
317 	case 3:
318 		prefix = '[WARN] ';
319 		func = 'warn';
320 		break;
321 	case 4:
322 		prefix = '[ERROR] ';
323 		func = 'error';
324 		break;
325 	case 5:
326 		prefix = '[CRITICAL] ';
327 		func = 'error';
328 		break;
329 	case 6:		//debug-level "disabled" -> do nothing
330 		return; /////////////////// EARLY EXIT //////////
331 	default:
332 		prefix = '[UNDEF_LOG_LEVEL_'+logLevel+'] ';
333 		func = 'log';
334 		break;
335 	}
336 	console[func](prefix + loggerName + msg);
337 }
338 
339 
340 //enable tracing?
341 /**
342  * configuration value for enabling/disabling tracing in log-output
343  * @private
344  * @type Object
345  * @memberOf Logger.prototype
346  */
347 var tmpTraceConfig = module.config().trace;
348 if(tmpTraceConfig !== false || (tmpTraceConfig !== null && typeof tmpTraceConfig === 'object' && tmpTraceConfig.trace === true)){
349 
350 	/**
351 	 * options object for tracing
352 	 * @private
353 	 * @type Object
354 	 * @memberOf Logger.prototype
355 	 */
356 	var pnTraceOptions = tmpTraceConfig === true? void(0) : tmpTraceConfig;
357 	/**
358 	 * setting for trace-depth (i.e. stack-depth)
359 	 * @private
360 	 * @type Boolean
361 	 * @memberOf Logger.prototype
362 	 */
363 	var isFullStackDepth = pnTraceOptions && pnTraceOptions.depth === "full";
364 	
365 	/**
366 	 * proxy object for storing the original implementation
367 	 * of {@link Logger.prototype#print} function.
368 	 * 
369 	 * (only used, if tracing is enabled!)
370 	 * 
371 	 * @private
372 	 * @type Function
373 	 * @memberOf Logger.prototype
374 	 */
375 	var pnOriginal = print;
376 	
377 	//do enable tracing: append stacktrace to messages in print-function
378 	if(isFullStackDepth){
379 		
380 		//NOTE code duplication for the sake of a more efficient print function
381 		
382 		/**
383 		 * Extension for {@link Logger.prototype#print} function with tracing.
384 		 * 
385 		 * This extension prints the full stack trace in log-output.
386 		 * 
387 		 * (only used, if tracing is enabled!)
388 		 * 
389 		 * @private
390 		 * @name printFullStack
391 		 * @function
392 		 * @memberOf Logger.prototype
393 		 */
394 		print = function printFullStack(loggerName, logLevel, msg, isErrInvoked){
395 			if(typeof msg === 'undefined' || msg === null){
396 				msg = '';
397 			}
398 			//if isErrInvoked is TRUE: this function was invoked via additional printe()-call
399 			// => need to take 1 more step down the stack
400 			msg += '\n  ' + stacktrace(pnTraceOptions).slice(isErrInvoked? 6 : 5).join('\n  ');
401 			pnOriginal.call(this, loggerName, logLevel, msg);
402 		};
403 	}
404 	else {
405 		
406 		//NOTE code duplication for the sake of a more efficient print function
407 		
408 		/**
409 		 * Extension for {@link Logger.prototype#print} function with tracing.
410 		 * 
411 		 * This extension prints only the first entry of the stack trace in log-output.
412 		 * 
413 		 * (only used, if tracing is enabled!)
414 		 * 
415 		 * @private
416 		 * @name printStack
417 		 * @function
418 		 * @memberOf Logger.prototype
419 		 */
420 		print = function printStack(loggerName, logLevel, msg, isErrInvoked){
421 			if(typeof msg === 'undefined' || msg === null){
422 				msg = '';
423 			}
424 			//if isErrInvoked is TRUE: this function was invoked via additional printe()-call
425 			// => need to take 1 more step down the stack
426 			msg += '\n  ' + stacktrace(pnTraceOptions)[isErrInvoked? 6 : 5];
427 			pnOriginal.call(this, loggerName, logLevel, msg);
428 		};
429 	}
430 
431 }
432 
433 /**
434  * Constructor-Method of Class Logger<br>
435  * @constructor
436  * @class Logger
437  * @name Logger
438  * 
439  * @param {String} theName
440  * 					the name / ID for the logger
441  * @param {String|Number} [theLevel] OPTIONAL
442  * 					the log-level.
443  * 					If omitted, the logger will use
444  * 					the default log-level
445  *  
446  * @see #getAsLevel
447  * @see #getLevel
448  */
449 function Logger(theName, theLevel){
450 	
451 	//the name (/key) for the logger instance
452 	this.name = '';
453 	if(typeof theName !== 'undefined'){
454 		this.name = '['+theName+'] ';
455 	}
456 	
457 	if(typeof theLevel !== 'undefined'){
458 		if(typeof theLevel !== 'number'){
459 			theLevel = getAsLevel(theLevel);
460 		}
461 		
462 		this.level = theLevel;
463 	}
464 }
465 
466 Logger.prototype =
467 /** @lends Logger# */
468 {//public instance members
469 	
470 	/**
471 	 * Get the current log-level:
472 	 * if a specific log-level for this Logger instance is set,
473 	 * this value is returned.
474 	 * Otherwise, the default log-level as returned by {@link mmir.Logging#getDefaultLogLevel}
475 	 * is used.
476 	 * 
477 	 * Log-levels:
478 	 * <ul>
479 	 * 	<li>0: verbose</li>
480 	 * 	<li>1: debug</li>
481 	 * 	<li>2: info</li>
482 	 * 	<li>3: warn</li>
483 	 * 	<li>4: error</li>
484 	 * 	<li>5: critical</li>
485 	 * 	<li>6: disabled</li>
486 	 * <ul>
487 	 * 
488 	 * @returns {Number} the logging level
489 	 * 
490 	 * @see #setLevel
491 	 */
492     getLevel : function(){
493     	
494     	if(typeof this.level !== 'undefined'){
495     		return this.level;
496     	}
497     	
498     	//return default/global logging-level:
499     	return _level;
500     },
501     /**
502      * Set the logging level.
503      * 
504      * @param {String|Number} loggingLevel
505      * 						if {Number} the logging level as a number
506      *                      if {String} the logging level as a string (see {@link #getLevel})
507      *                      
508 	 * @see #getLevel
509      */
510     setLevel : function(loggingLevel){
511     	
512     	if(typeof loggingLevel !== 'number'){
513     		loggingLevel = getAsLevel(loggingLevel);
514     	}
515     	
516     	this.level = loggingLevel;
517     },
518     /**
519      * 
520      * Print a log message, if at least <code>debug</code> log-level is set.
521      * 
522      * @param {String} [className] OPTIONAL
523      * 			the name of the class/object from which the logging is invoked from
524      * @param {String} [funcName] OPTIONAL
525      * 			the name of the function (within the class) from which the logging is invoked from
526      * @param {String} msg
527      * 			the log message
528      * @param {Error} [error] OPTIONAL
529      * 			an error object: if available, its message and error-stack will be print to the output
530 	 * @public
531 	 */
532     log: function(className, funcName, msg, error){
533     	if(this.isDebug()){
534     		printe(this.name, 1 /*getAsLevel('debug')*/, className, funcName, msg, error);
535     	}
536     },
537 
538     /**
539      * 
540      * Print a <em>verbose</em> log message, if at least <code>verbose</code> (0) log-level is set.
541      * 
542      * @param {String} [className] OPTIONAL
543      * 			the name of the class/object from which the logging is invoked from
544      * @param {String} [funcName] OPTIONAL
545      * 			the name of the function (within the class) from which the logging is invoked from
546      * @param {String} msg
547      * 			the log message
548 	 * @public
549 	 */
550     //TODO implement/add helpers for file-logging (+ CSV data helpers etc)
551     verbose : function(className, funcName, msg){
552     	if(this.isVerbose()){
553     		print( this.name, 0 /*getAsLevel('verbose')*/, createMsg(className, funcName, msg));
554     	}
555     },
556 
557     /**
558      * 
559      * Print a <em>debug</em> log message, if at least <code>debug</code> (1) log-level is set.
560      * 
561      * @param {String} [className] OPTIONAL
562      * 			the name of the class/object from which the logging is invoked from
563      * @param {String} [funcName] OPTIONAL
564      * 			the name of the function (within the class) from which the logging is invoked from
565      * @param {String} msg
566      * 			the log message
567 	 * @public
568 	 */
569     debug : function(className, funcName, msg){
570     	if(this.isDebug()){
571     		print( this.name, 1 /*getAsLevel('debug')*/, createMsg(className, funcName, msg));
572     	}
573     },
574 
575     /**
576      * 
577      * Print an <em>information</em> log message, if at least <code>info</code> (2) log-level is set.
578      * 
579      * @param {String} [className] OPTIONAL
580      * 			the name of the class/object from which the logging is invoked from
581      * @param {String} [funcName] OPTIONAL
582      * 			the name of the function (within the class) from which the logging is invoked from
583      * @param {String} msg
584      * 			the log message
585 	 * @public
586 	 */
587     info : function(className, funcName, msg){
588     	if(this.isInfo()){
589     		print( this.name, 2 /*getAsLevel('info')*/, createMsg(className, funcName, msg));
590     	}
591     },
592 
593     /**
594      * 
595      * Print a <em>warning</em> log message, if at least <code>warn</code> (3) log-level is set.
596      * 
597      * @param {String} [className] OPTIONAL
598      * 			the name of the class/object from which the logging is invoked from
599      * @param {String} [funcName] OPTIONAL
600      * 			the name of the function (within the class) from which the logging is invoked from
601      * @param {String} msg
602      * 			the log message
603 	 * @public
604 	 */
605     warn : function(className, funcName, msg){
606     	if(this.isWarn()){
607     		print( this.name, 3 /*getAsLevel('warn')*/, createMsg(className, funcName, msg));
608     	}
609     },
610 
611     /**
612      * 
613      * Print an <em>error</em> log message, if at least <code>error</code> (4) log-level is set.
614      * 
615      * @param {String} [className] OPTIONAL
616      * 			the name of the class/object from which the logging is invoked from
617      * @param {String} [funcName] OPTIONAL
618      * 			the name of the function (within the class) from which the logging is invoked from
619      * @param {String} msg
620      * 			the log message
621      * @param {Error} [error] OPTIONAL
622      * 			an error object: if available, its message and error-stack will be print to the output
623 	 * @public
624 	 */
625     error : function(className, funcName, msg, error){
626     	if(this.isError()){
627     		printe(this.name, 4 /*getAsLevel('error')*/, className, funcName, msg, error);
628     	}
629     },
630 
631     /**
632      * 
633      * Print a <em>critical</em> (exception) log message, if at least <code>critical</code> (5) log-level is set.
634      * 
635      * @param {String} [className] OPTIONAL
636      * 			the name of the class/object from which the logging is invoked from
637      * @param {String} [funcName] OPTIONAL
638      * 			the name of the function (within the class) from which the logging is invoked from
639      * @param {String} msg
640      * 			the log message
641      * @param {Error} [error] OPTIONAL
642      * 			an error object: if available, its message and error-stack will be print to the output
643 	 * @public
644 	 */
645     critical : function(className, funcName, msg, error){
646     	if(this.isCritical()){
647     		printe(this.name, 5 /*getAsLevel('critical')*/, className, funcName, msg, error);
648     	}
649     },
650 
651     /**
652      * 
653      * Check if the current log-level is at least <code>verbose</code>.
654      * 
655      * @returns {Boolean}
656      * 				<code>true</code> if at least log-level <code>verbose</code> (0) 
657 	 * @public
658 	 * 
659 	 * @see #verbose
660 	 */
661     isVerbose : function(loggerName){
662     	return this.getLevel() <= 0;// getAsLevel('verbose');
663     },
664 
665     /**
666      * 
667      * Check if the current log-level is at least <code>debug</code>.
668      * 
669      * @returns {Boolean}
670      * 				<code>true</code> if at least log-level <code>debug</code> (1) 
671 	 * @public
672 	 * 
673 	 * @see #debug
674 	 */
675     isDebug : function(loggerName){
676     	return this.getLevel() <= 1;//getAsLevel('debug');
677     },
678 
679     /**
680      * 
681      * Check if the current log-level is at least <code>info</code>.
682      * 
683      * @returns {Boolean}
684      * 				<code>true</code> if at least log-level <code>info</code> (2) 
685 	 * @public
686 	 * 
687 	 * @see #info
688 	 */
689     isInfo : function(loggerName){
690     	return this.getLevel() <= 2;//getAsLevel('info');
691     },
692 
693     /**
694      * 
695      * Check if the current log-level is at least <code>warn</code>.
696      * 
697      * @returns {Boolean}
698      * 				<code>true</code> if at least log-level <code>warn</code> (3) 
699 	 * @public
700 	 * 
701 	 * @see #warn
702 	 */
703     isWarn : function(loggerName){
704     	return this.getLevel() <= 3;//getAsLevel('warn');
705     },
706 
707     /**
708      * 
709      * Check if the current log-level is at least <code>error</code>.
710      * 
711      * @returns {Boolean}
712      * 				<code>true</code> if at least log-level <code>error</code> (4) 
713 	 * @public
714 	 * 
715 	 * @see #error
716 	 */
717     isError : function(loggerName){
718     	return this.getLevel() <= 4;//getAsLevel('error');
719     },
720 
721     /**
722      * 
723      * Check if the current log-level is at least <code>critical</code>.
724      * 
725      * @returns {Boolean}
726      * 				<code>true</code> if at least log-level <code>critical</code> (5) 
727 	 * @public
728 	 * 
729 	 * @see #critical
730 	 */
731     isCritical : function(loggerName){
732     	return this.getLevel() <= 5;//getAsLevel('critical');
733     },
734 
735     /**
736      * 
737      * Check if the current log-level is at least <code>disabled</code>.
738      * 
739      * @returns {Boolean}
740      * 				<code>true</code> if at least log-level <code>disable</code> (6) 
741 	 * @public
742 	 * 
743 	 * @see #getLevel
744 	 */
745     isDisabled : function(loggerName){
746     	return this.getLevel() <= 6;//getAsLevel('disabled');
747     }
748 };
749 
750 //define alias'
751 
752 /**
753  * Alias for {@link #log}.
754  * 
755  * @public
756  * @var {Function} Logger#l
757  */
758 Logger.prototype.l = function(){
759 	return this.log.apply(this, arguments);
760 };
761 
762 /**
763  * Alias for {@link #verbose}.
764  * 
765  * @public
766  * @var {Function} Logger#v
767  */
768 Logger.prototype.v = function(){
769 	return this.verbose.apply(this, arguments);
770 };
771 
772 /**
773  * Alias for {@link #debug}.
774  * 
775  * @public
776  * @var {Function} Logger#d
777  */
778 Logger.prototype.d = function(){
779 	return this.debug.apply(this, arguments);
780 };
781 
782 /**
783  * Alias for {@link #info}.
784  * 
785  * @public
786  * @var {Function} Logger#i
787  */
788 Logger.prototype.i = function(){
789 	return this.info.apply(this, arguments);
790 };
791 
792 /**
793  * Alias for {@link #warn}.
794  * 
795  * @public
796  * @var {Function} Logger#w
797  */
798 Logger.prototype.w = function(){
799 	return this.warn.apply(this, arguments);
800 };
801 
802 /**
803  * Alias for {@link #error}.
804  * 
805  * @public
806  * @var {Function} Logger#e
807  */
808 Logger.prototype.e = function(){
809 	return this.error.apply(this, arguments);
810 };
811 
812 /**
813  * Alias for {@link #critical}.
814  * 
815  * @public
816  * @var {Function} Logger#c
817  */
818 Logger.prototype.c = function(){
819 	return this.critical.apply(this, arguments);
820 };
821 
822 /**
823  * @scope Logger#
824  */
825 
826 /**
827  * Alias for {@link #isVerbose}.
828  * 
829  * @public
830  * @var {Function} Logger#isv
831  */
832 Logger.prototype.isv = function(){
833 	return this.isVerbose.apply(this, arguments);
834 };
835 
836 /**
837  * Alias for {@link #isDebug}.
838  * 
839  * @public
840  * @var {Function} Logger#isd
841  */
842 Logger.prototype.isd = function(){
843 	return this.isDebug.apply(this, arguments);
844 };
845 
846 /**
847  * Alias for {@link #isInfo}.
848  * 
849  * @public
850  * @var {Function} Logger#isi
851  */
852 Logger.prototype.isi = function(){
853 	return this.isInfo.apply(this, arguments);
854 };
855 
856 /**
857  * Alias for {@link #isWarn}.
858  * 
859  * @public
860  * @var {Function} Logger#isw
861  */
862 Logger.prototype.isw = function(){
863 	return this.isWarn.apply(this, arguments);
864 };
865 
866 /**
867  * Alias for {@link #isError}.
868  * 
869  * @public
870  * @var {Function} Logger#ise
871  */
872 Logger.prototype.ise = function(){
873 	return this.isError.apply(this, arguments);
874 };
875 
876 /**
877  * Alias for {@link #isCritical}.
878  * 
879  * @public
880  * @var {Function} Logger#isc
881  */
882 Logger.prototype.isc = function(){
883 	return this.isCrictial.apply(this, arguments);
884 };
885 
886 
887 /**
888  * @private
889  * @type Logger
890  * @memberOf mmir.Logging#
891  */
892 var _defaultLogger = new Logger();
893 //default logger always has default/global log-level:
894 /**
895  * @inheritdoc
896  */
897 _defaultLogger.getLevel = function(){
898 	return _level;
899 };
900 
901 //the instance for the Logging factory:
902 var instance =
903 /** @lends mmir.Logging.prototype */
904 {//public API
905 		
906 	/**
907 	 * Creates a {@link Logger} instance.
908 	 * 
909 	 * If a logger for <code>loggerName</code> already exists,
910 	 * the existing logger is returned (instead of creating a new one).
911 	 * 
912 	 * @param {String|Object} [loggerName]
913 	 * 			If String: a name / ID for the logger that should be created / retrieved.<br>
914 	 * 			If Object: an requirejs <code>module</code> object, i.e. should contain properties
915 	 * 							<code>id</code> (String) which will set the <code>loggerName</code>, and a property/function 
916 	 * 							<code>config</code> (Function) that returns an object with property
917 	 * 							<code>logLevel</code> (i.e. <code>config().logLevel</code> should be valid).<br>
918 	 * 			If omitted, the default logger will be returned.
919 	 * @param {String} [logLevel]
920 	 * 			a name / ID for the logger that should be created / retrieved.
921 	 * 			If omitted, the default logger will be returned.
922 	 * 
923 	 * @returns {Logger} the created (or retrieved) logger
924 	 * 
925 	 * @memberOf mmir.Logging.prototype
926 	 * @public
927 	 * 
928 	 * @see Logger
929 	 * @see Logger#setLevel
930 	 */
931     create: function(loggerName, logLevel){
932     	
933     	//special argument: is first argument is a (requirejs) module?
934     	if(typeof loggerName === 'object' && loggerName && loggerName.id && typeof loggerName.config === 'function'){
935     		//extract parameters from module object:
936     		logLevel = loggerName.config().logLevel;//<- may be undefined
937     		loggerName = loggerName.id;
938     	}
939     		
940         //no logger specified: return default logger
941         if(! loggerName){
942         	return _defaultLogger;
943         }
944         
945         if(typeof loggerName !== 'string'){
946         	loggerName = loggerName.toString();
947         }
948         
949         //return specified logger
950         var theLogger = _loggers.get(loggerName);
951         if(typeof theLogger === 'undefined'){
952         	//create, if not existing
953         	var theNewLogger = new Logger(loggerName, logLevel);
954         	_loggers.put(loggerName, theNewLogger);
955         	
956         	return theNewLogger;
957         }
958         
959         if(typeof logLevel !== 'undefined'){
960         	theLogger.setLevel(logLevel);
961         }
962         
963         return theLogger;
964     },
965     /**
966      * Sets the default log-level.
967      * 
968      * This setting is used by loggers, that do not have
969      * a specific log-level set.
970      * 
971      * @param {Number} theLevel
972      * 			the log level: a number between 0 (verbose) and 6 (disabled)
973      * 
974 	 * @public
975 	 * 
976 	 * @see #getDefaultLogLevel
977 	 * @see Logger#getLevel
978 	 */
979     setDefaultLogLevel: function(theLevel){
980     	_level = theLevel;
981     },
982     /**
983      * Sets the default log-level.
984      * 
985      * @returns {Number}
986      * 			the log level: a number between 0 (verbose) and 6 (disabled)
987      * 
988 	 * @public
989 	 * @see #setDefaultLogLevel
990 	 * @see Logger#getLevel
991 	 */
992     getDefaultLogLevel: function(){
993     	return _level;
994     },
995     /**
996      * Print log output with default logger.
997 	 * @public
998 	 * @see Logger#log
999 	 */
1000     log: function(){
1001     	_defaultLogger.log.apply(_defaultLogger, arguments);
1002     },
1003     /**
1004      * Print verbose output with default logger.
1005 	 * @public
1006 	 * @see Logger#verbose
1007 	 */
1008     verbose: function(){
1009     	_defaultLogger.verbose.apply(_defaultLogger, arguments);
1010     },
1011     /**
1012      * Print debug message with default logger.
1013 	 * @public
1014 	 * @see Logger#debug
1015 	 */
1016     debug: function(){
1017     	_defaultLogger.debug.apply(_defaultLogger, arguments);
1018     },
1019     /**
1020      * Print information message with default logger.
1021 	 * @public
1022 	 * @see Logger#info
1023 	 */
1024     info: function(){
1025     	_defaultLogger.info.apply(_defaultLogger, arguments);
1026     },
1027     /**
1028      * Print warning message with default logger.
1029 	 * @public
1030 	 * @see Logger#warn
1031 	 */
1032     warn: function(){
1033     	_defaultLogger.warn.apply(_defaultLogger, arguments);
1034     },
1035     /**
1036      * Print error with default logger.
1037 	 * @public
1038 	 * @see Logger#error
1039 	 */
1040     error: function(){
1041     	_defaultLogger.error.apply(_defaultLogger, arguments);
1042     }//,
1043 //    isDebug : function(loggerName){
1044 //    	return _level <= getAsLevel('debug');
1045 //    },
1046 //    isInfo : function(loggerName){
1047 //    	return _level <= getAsLevel('info');
1048 //    },
1049 //    isWarn : function(loggerName){
1050 //    	return _level <= getAsLevel('warn');
1051 //    },
1052 //    isError : function(loggerName){
1053 //    	return _level <= getAsLevel('error');
1054 //    }
1055 };
1056 
1057 //define alias'
1058 instance.get = instance.create;
1059 
1060 
1061 return instance;
1062     
1063 });
1064