DIR : /home/kozerus/public_html/pn/uize/site-source/js/Uize/Service.js

/home/kozerus/public_html/pn/uize/site-source/js/Uize

/*______________
|       ______  |   U I Z E    J A V A S C R I P T    F R A M E W O R K
|     /      /  |   ---------------------------------------------------
|    /    O /   |    MODULE : Uize.Service Class
|   /    / /    |
|  /    / /  /| |    ONLINE : http://www.uize.com
| /____/ /__/_| | COPYRIGHT : (c)2012-2016 UIZE
|          /___ |   LICENSE : Available under MIT License or GNU General Public License
|_______________|             http://www.uize.com/license.html
*/

/* Module Meta Data
	type: Class
	importance: 7
	codeCompleteness: 0
	docCompleteness: 5
*/

/*?
	Introduction
		The =Uize.Service= module defines a base class from which classes that define services can inherit.

		*DEVELOPERS:* `Chris van Rensburg`
*/

Uize.module ({
	name:'Uize.Service',
	superclass:'Uize.Class',
	builder:function (_superclass) {
		'use strict';

		var
			/*** Variables for Scruncher Optimization ***/
				_undefined,
				_false = false,
				_true = true,

			/*** constants ***/
				_SERVICE_TAKING_TOO_LONG = 5000
		;

		/*** Private Instance Methods ***/
			function _warn (m,_message) {
				m.fire ({name:'warning',warning:_message});
			}

			function _methodCaller (m,_methodName) {
				return function () {return m [_methodName].apply (m,arguments)};
			}

		return _superclass.subclass ({
			staticProperties:{
				_serviceMethods:{}
			},

			staticMethods:{
				serviceMethods:function (_serviceMethods) {
					var
						m = this,
						_thisServiceMethods = m._serviceMethods,
						_serviceMethodPublicWrappers = {}
					;
					function _declareServiceMethod (_methodName,_methodProfile) {
						var _isInitMethod = _methodName == 'init';

						function _methodError (_message) {return '<< ' + _methodName + ' >> ' + _message}

						if (m.prototype [_methodName])
							throw new Error (
								_methodError ('You may not override a non-service public method with a service method')
							)
						;

						_thisServiceMethods [_methodName] = _methodProfile || (_methodProfile = {});

						/* NOTES:
							normalize method profile

							eg.
							{
								async: true (default) | false,
								params: {...}
							}
						*/
						_methodProfile.async = _methodProfile.async !== _false;

						_serviceMethodPublicWrappers [_methodName] = function (_params,_callback) {
							var
								m = this,
								_adapter = m.get ('adapter'),
								_methodIsAsync = _methodProfile.async
							;
							if (!_methodIsAsync) {
								if (!_adapter)
									throw new Error (
										_methodError (
											'To call a synchronous service method, a service adapter must be set and the service must be initialized'
										)
									)
								;
								if (!_isInitMethod && !m.get ('initialized'))
									throw new Error (
										_methodError (
											'In order to call a synchronous service method, the service must already be initialized'
										)
									)
								;
							}
							if (_params == _undefined) {
								_params = {};
							} else if (typeof _params != 'object') {
								throw new Error (_methodError ('First argument (params) must be an object, null, or undefined'));
							}
							var
								_adapterMethodWasAsync = _false,
								_timeCalled,
								_timeReturned,
								_takingTooLongTimeout,
								_result,
								_error,
								_handleReturnFromAdapterMethod = function () {
									_takingTooLongTimeout && clearTimeout (_takingTooLongTimeout);
									function _callCallback () {
										var _onSuccess, _onError;
										if (_callback) {
											var _typeofCallback = typeof _callback;
											if (_typeofCallback == 'function') {
												_onSuccess = _callback;
											} else if (_typeofCallback == 'object') {
												_onSuccess = _callback.onSuccess;
												_onError = _callback.onError;
											}
										}
										if (_error) {
											if (_onError) {
												_onError (_error);
											} else {
												typeof _error == 'string'
													? (_error = new Error (_methodError (_error)))
													: (_error.message = _methodError (_error.message))
												;
												throw _error;
											}
										} else {
											_isInitMethod && m.set ('initialized',_true);
											_onSuccess && _onSuccess (_result);
										}
									}
									if (_timeReturned !== _undefined) {
										throw new Error (_methodError ('Service adapter method should only return once'));
									} else {
										_timeReturned = Uize.now ();
										var _adapterMethodDuration = _timeReturned - _timeCalled;
										_adapterMethodDuration > _SERVICE_TAKING_TOO_LONG &&
											_warn (
												m,
												_methodError(
													'Service adapter method took too long to return (' + _adapterMethodDuration + 'ms)'
												)
											)
										;
										if (_methodProfile.async) {
											_adapterMethodWasAsync ? _callCallback () : setTimeout (_callCallback,0);
										} else {
											if (_adapterMethodWasAsync) {
												throw new Error (
													_methodError (
														'Service method is declared as synchronous, but implementation in adapter is asynchronous'
													)
												);
											} else {
												_callCallback ();
											}
										}
									}
								},
								_callAdapterMethod = function () {
									if (
										_adapter [_methodName] (
											_params,
											function (_response) {
												_result = _response;
												_handleReturnFromAdapterMethod ();
											},
											function (_errorResponse) {
												_error = _errorResponse || {};
												_handleReturnFromAdapterMethod ();
											}
										) !== _undefined
									)
										throw new Error (
											_methodError (
												'Service adapter method should always provide its result through a callback, not a return statement'
											)
										)
									;
									_adapterMethodWasAsync = _true;
								}
							;

							// now ready to start the call
							_timeCalled = Uize.now ();
							if (_methodIsAsync)
								_takingTooLongTimeout = setTimeout (
									function () {
										var _initialized = m.get ('initialized');
										_warn (
											m,
											_methodError (
												_adapter && _initialized
													? 'Service adapter method taking too long to return'
													: (
														'Taking too long to be ready to call service adapter method (' +
															'adapter ' + (_adapter ? '' : 'not ') + 'set, ' +
															(_initialized ? '' : 'not ') + 'initialized' +
														')'
													)
											)
										);
									},
									_SERVICE_TAKING_TOO_LONG
								)
							;
							if (_isInitMethod) {
								_params.serviceInterface = {
									fire:_methodCaller (m,'fire'),
									wire:_methodCaller (m,'wire'),
									set:_methodCaller (m,'set'),
									get:_methodCaller (m,'get')
								};
								_params.service = m;
								m.once ('adapter',_callAdapterMethod);
							} else {
								if (!_adapter) {
									_warn (m,_methodError ('Adapter is not yet set when service method is called'));
								} else if (!m.get ('initialized')) {
									_warn (
										m,
										_methodError (
											'Service adapter is set but not yet initialized when service method is called'
										)
									);
								}
								m.once (
									'adapter',
									function () {
										_adapter = m.get ('adapter');
										m.once ('initialized',_callAdapterMethod);
									}
								);
							}
							return _result;
						};
					}
					if (arguments.length != 1 || typeof _serviceMethods != 'object')
						_serviceMethods = [].slice.call (arguments)
					;
					Uize.forEach (
						_serviceMethods,
						Uize.isArray (_serviceMethods)
							? function (_methodName) {_declareServiceMethod (_methodName)}
							: function (_methodProfile,_methodName) {_declareServiceMethod (_methodName,_methodProfile)}
					);
					Uize.copyInto (m.prototype,_serviceMethodPublicWrappers);
					/*?
						Static Methods
							Uize.Service.serviceMethods
								.

								EXAMPLE
								..........................................
								var FileSystem = Uize.Service.subclass ();
								FileSystem.serviceMethods ({
									readFile:{
										async:false
									},
									writeFile:{
										async:false
									},
									getFiles:{
										async:false
									},
									getFolder:{
										async:false
									},
									// etc.
									// etc.
								});
								..........................................
					*/
				}
			},

			stateProperties:{
				_adapter:{
					name:'adapter',
					conformer:function (_adapter) {
						if (typeof _adapter == 'string') {
							var _adapterClass = Uize.getModuleByName (_adapter);
							if (_adapterClass) {
								_adapter = new _adapterClass;
							} else {
								throw new Error (
									'The adapter module ' + _adapter + ' must be required and loaded first if you wish to set an adapter by module name'
								);
							}
						}
						if (_adapter != _undefined) {
							// validate the service adapter
							var _missingServiceMethods = [];
							Uize.forEach (
								this.constructor._serviceMethods,
								function (_serviceMethodProfile,_serviceMethod) {
									typeof _adapter [_serviceMethod] != 'function' &&
										_missingServiceMethods.push (_serviceMethod)
									;
								}
							);
							if (_missingServiceMethods.length) {
								_adapter = _undefined;
								throw new Error (
									'Service module adapter is missing implementations for service methods: ' + _missingServiceMethods.sort ().join (', ')
								);
							}
						}
						return _adapter;
					},
					onChange:function () {this.set ({initialized:_false})}
					/*?
						State Properties
							adapter
								.
					*/
				},
				_initialized:{
					name:'initialized',
					value:_false
					/*?
						State Properties
							initialized
								.
					*/
				}
			}
		});
	}
});

//


koh5_pano



Your browser does not support the HTML5 canvas element.


Drag mouse to navigate.

Navigation





17.Aug.2010, Martin Wengenmayer