(function($){var cachedSMDs={};function Service(){this.init.apply(this,arguments);}
Service.prototype.constructor=Service;$.extend(Service.prototype,{strictArgChecks:true,serviceUrl:"",bustCache:false,contentType:"application/json-rpc",runningRequest:null,init:function(args){if(args){if(typeof(args)=='string'){var url=args,scope=this;if(typeof(cachedSMDs[url])!='undefined')
{this.processSmd(cachedSMDs[url]);}
else
{$.ajax({url:url,async:false,dataType:'json',success:function(smd){cachedSMDs[url]=smd;scope.processSmd(smd);},error:function(){throw new Error("Unable to load SMD from "+url);}});}}else if(args.smd){this.processSmd((typeof(args.smd)=='string'?$.evalJSON(args.smd):args.smd));}else{}}
this.callbacks={success:[],error:[]};this.lastSubmissionId=0;},callRemote:function(method,parameters,url){if(this.runningRequest!=null){console.log("Aborting...");this.runningRequest.abort();}
this.runningRequest=$.ajax({url:url||this.serviceUrl,type:'POST',dataType:'json',contentType:this.contentType,processData:false,data:this.createRequest(method,parameters),success:this.resultCallback(),error:this.errorCallback()});return this;},call:function(method,parameters){if($.isFunction(this[method]))
return this[method].apply(this,parameters);else
return this.callRemote(method,parameters);},createRequest:function(method,params){var req={"params":params,"method":method,"id":++this.lastSubmissionId};var data=$.toJSON(req);return data;},parseResults:function(obj){if(typeof(obj)=='object'){if("result"in obj){return obj.result;}
if("Result"in obj){return obj.Result;}
if("ResultSet"in obj){return obj.ResultSet;}}
return obj;},errorCallback:function(){var scope=this;return function(){var args=arguments;scope.runningRequest=null;$.each(scope.callbacks.error,function(index,o){o.callback.apply(o.scope,args);});}},addErrorCallback:function(callback,scope){if($.isFunction(callback)){this.callbacks.error.unshift({callback:callback,scope:scope});}
return this;},resultCallback:function(){var scope=this;var tf=function(obj){scope.runningRequest=null;if(obj.error!=null){var err;if(typeof obj.error=='object'){err=new Error(obj.error.message);err.code=obj.error.code;err.error=obj.error.error;}else{err=new Error(obj.error);}
err.id=obj.id;err.errorObject=obj;scope.errorCallback()(err);}else{var result=scope.parseResults(obj);$.each(scope.callbacks.success,function(index,o){o.callback.call(o.scope,result);});}};return tf;},addCallback:function(callback,scope){if($.isFunction(callback)){this.callbacks.success.unshift({callback:callback,scope:(typeof(scope)=='object'?scope:null)});}
return this;},generateMethod:function(method,parameters,url){var scope=this;return function(){if((scope.strictArgChecks)&&(parameters!=null)&&(arguments.length!=parameters.length)){throw new Error("Invalid number of parameters for remote method.");}else{scope.callRemote(method,$.makeArray(arguments),url);}
return scope;};},processSmd:function(object){if(object.methods){var scope=this;$.each(object.methods,function(index,m){if(m&&m.name){scope[m.name]=scope.generateMethod(m.name,m.parameters,m.url||m.serviceUrl||m.serviceURL);if(!$.isFunction(scope[m.name])){throw new Error("RpcService: Failed to create"+m.name+"()");}}});}
this.serviceUrl=object.serviceUrl||object.serviceURL;this.required=object.required;this.smd=object;}});$.rpc={Service:function(args){return new Service(args);},parseRpcMethod:function(method){if(typeof(method)=='string'){var params=method.split('.');return{className:params[0],method:params[1]};}
return null;}};})(jQuery);
