      1 /*
      2  *  Copyright (C) 2008-2009 WaveMaker Software, Inc.
      3  *
      4  *  This file is part of the WaveMaker Client Runtime.
      5  *
      6  *  Licensed under the Apache License, Version 2.0 (the "License");
      7  *  you may not use this file except in compliance with the License.
      8  *  You may obtain a copy of the License at
      9  *
     10  *      http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  *  Unless required by applicable law or agreed to in writing, software
     13  *  distributed under the License is distributed on an "AS IS" BASIS,
     14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  *  See the License for the specific language governing permissions and
     16  *  limitations under the License.
     17  */
     18 dojo.provide("wm.base.components.Service");
     19 dojo.require("wm.base.Component");
     20
     21 /**
     22 	Component that can be configured to perform a task.
     23 	<br/><br/>
     24 	@name wm.Service
     25 	@class
     26 	@extends wm.Component
     27 */
     28 dojo.declare("wm.Service", wm.Component, {
     29 	/** @lends wm.Service.prototype */
     30 	_operations: {},
     31 	/**
     32 		Result data (if any) returned from the last invocation.
     33 	*/
     34 	result: null,
     35 	/**
     36 		Error data (if any) returned from the last invocation.
     37 	*/
     38 	error: null,
     39 	getOperationsList: function() {
     40 		var l = [];
     41 		for (var i in this._operations)
     42 			l.push(i);
     43 		l.sort();
     44 		return l;
     45 	},
     46 	getOperation: function(inOperation) {
     47 		return this._operations[inOperation];
     48 	},
     49 	initService: function() {
     50 	},
     51 	/**
     52 		Invoke a method on this service object with arguments.
     53 		<br/><br/>
     54 		Invocations may be asynchronous. Responses are available
     55 		via the returned Deferred object or from the
     56 		<a href="#onResult">onResult</a> and
     57 		<a href="#onError">onError</a> events.
     58 		@param {String} inMethod The method to invoke on this object.
     59 		@param {Array} inArgs An array of parameters for the method.
     60 		@returns {dojo.Deferred} Response handler object.
     61 	*/
     62 	invoke: function(inMethod, inArgs) {
     63 		var
     64 			d = new dojo.Deferred(),
     65 			m = this[inMethod];
     66 		if (m) {
     67 			var result = m.apply(this, inArgs);
     68 			this.onResult();
     69 			wm.onidle(function() {
     70 				d.callback(result);
     71 			});
     72 		} else {
     73 			this.onError();
     74 			wm.onidle(function() {
     75 				d.errback("operation: " + inMethod + " does not exist.");
     76 			});
     77 		}
     78 		return d;
     79 	},
     80 	/**
     81 		Event that fires after a succesful service invocation.
     82 		@param {Any} inResult Any result data returned from the service.
     83 	*/
     84 	onResult: function(inResult) {
     85 		this.error = null;
     86 		return this.result = inResult;
     87 	},
     88 	/**
     89 		Event that fires after a service invocation has resulted in an error.
     90 		@param {Any} inError Any error data returned from the service.
     91 	*/
     92 	onError: function(inError) {
     93 		this.result = null;
     94 		return this.error = inError;
     95 	}
     96 });
     97
     98 // FIXME: needs its own module
     99 // ==========================================================
    100 // Services registry (provides info about available services)
    101 // ==========================================================
    102
    103 wm.services = {
    104 	byName: {},
    105 	_services: {},
    106 	add: function(inService){
    107 		return wm.services.byName[inService.name] = inService;
    108 	},
    109 	remove: function(inService){
    110 		var n = inService.name;
    111 		this._destroyService(n);
    112 		delete wm.services.byName[n];
    113 	},
    114 	getNamesList: function() {
    115 		var l = [], services = wm.services.byName, s;
    116 		for (var i in services) {
    117 			s = services[i];
    118 			if (!s.clientHide)
    119 				l.push(i);
    120 		}
    121 		l.sort();
    122 		return l;
    123 	},
    124 	forEach: function(inFunction) {
    125 		wm.forEach(this.byName, function(s) {
    126 			inFunction(s);
    127 		});
    128 	},
    129 	clear: function() {
    130 		var n = wm.services.byName, s;
    131 		for (var i in n) {
    132 			s = n[i];
    133 			if (!s.isClientService)
    134 				this.remove(s);
    135 			else
    136 				this._destroyService(s);
    137 		}
    138 	},
    139 	getService: function(inName) {
    140 		var s;
    141 		if (inName) {
    142 			s = this._services[inName] || this._createService(inName);
    143 			if (!s._service)
    144 				s.initService();
    145 		}
    146 		return s;
    147 	},
    148 	_createService: function(inName) {
    149 		var
    150 			defaultCtor = "wm.JsonRpcService",
    151 			s = this.byName[inName];
    152 		if (!s)
    153 			s = this.add({name: inName, ctor: defaultCtor});
    154 		var ctor = dojo.getObject(s.ctor || defaultCtor);
    155 		// FIXME: we don't want to be streamed so don't include owner
    156 		// otoh without owner, we don't know how to resolve paths at designTime
    157 		var service = new ctor({name: inName, service: inName});
    158 		service.owner = dojo.getObject("studio.wip.app") || app;
    159 		return service;
    160 	},
    161 	_destroyService: function(inService) {
    162 		wm.fire(this._services[inService.name], "destroy");
    163 	}
    164 };
    165