org.activecomponents.webservice.jadex.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jadex-platform-webservice-websocket Show documentation
Show all versions of jadex-platform-webservice-websocket Show documentation
Jadex websocket webservice implementation
// https://github.com/joewalnes/reconnecting-websocket/blob/master/reconnecting-websocket.js
(function (global, factory) {
if (typeof define === 'function' && define.amd) {
define([], factory);
} else if (typeof module !== 'undefined' && module.exports){
module.exports = factory();
} else {
global.ReconnectingWebSocket = factory();
}
})(this, function () {
if (!('WebSocket' in window)) {
return;
}
function ReconnectingWebSocket(url, protocols, options) {
// Default settings
var settings = {
/** Whether this instance should log debug messages. */
debug: false,
/** Whether or not the websocket should attempt to connect immediately upon instantiation. */
automaticOpen: true,
/** The number of milliseconds to delay before attempting to reconnect. */
reconnectInterval: 1000,
/** The maximum number of milliseconds to delay a reconnection attempt. */
maxReconnectInterval: 30000,
/** The rate of increase of the reconnect delay. Allows reconnect attempts to back off when problems persist. */
reconnectDecay: 1.5,
/** The maximum time in milliseconds to wait for a connection to succeed before closing and retrying. */
timeoutInterval: 2000,
/** The maximum number of reconnection attempts to make. Unlimited if null. */
maxReconnectAttempts: null,
/** The binary type, possible values 'blob' or 'arraybuffer', default 'blob'. */
binaryType: 'blob'
}
if (!options) { options = {}; }
// Overwrite and define settings with options if they exist.
for (var key in settings) {
if (typeof options[key] !== 'undefined') {
this[key] = options[key];
} else {
this[key] = settings[key];
}
}
// These should be treated as read-only properties
/** The URL as resolved by the constructor. This is always an absolute URL. Read only. */
this.url = url;
/** The number of attempted reconnects since starting, or the last successful connection. Read only. */
this.reconnectAttempts = 0;
/**
* The current state of the connection.
* Can be one of: WebSocket.CONNECTING, WebSocket.OPEN, WebSocket.CLOSING, WebSocket.CLOSED
* Read only.
*/
this.readyState = WebSocket.CONNECTING;
/**
* A string indicating the name of the sub-protocol the server selected; this will be one of
* the strings specified in the protocols parameter when creating the WebSocket object.
* Read only.
*/
this.protocol = null;
// Private state variables
var self = this;
var ws;
var forcedClose = false;
var timedOut = false;
var eventTarget = document.createElement('div');
// Wire up "on*" properties as event handlers
eventTarget.addEventListener('open', function(event) { self.onopen(event); });
eventTarget.addEventListener('close', function(event) { self.onclose(event); });
eventTarget.addEventListener('connecting', function(event) { self.onconnecting(event); });
eventTarget.addEventListener('message', function(event) { self.onmessage(event); });
eventTarget.addEventListener('error', function(event) { self.onerror(event); });
// Expose the API required by EventTarget
this.addEventListener = eventTarget.addEventListener.bind(eventTarget);
this.removeEventListener = eventTarget.removeEventListener.bind(eventTarget);
this.dispatchEvent = eventTarget.dispatchEvent.bind(eventTarget);
/**
* This function generates an event that is compatible with standard
* compliant browsers and IE9 - IE11
*
* This will prevent the error:
* Object doesn't support this action
*
* http://stackoverflow.com/questions/19345392/why-arent-my-parameters-getting-passed-through-to-a-dispatched-event/19345563#19345563
* @param s String The name that the event should use
* @param args Object an optional object that the event will use
*/
function generateEvent(s, args) {
var evt = document.createEvent("CustomEvent");
evt.initCustomEvent(s, false, false, args);
return evt;
};
this.open = function (reconnectAttempt) {
ws = new WebSocket(self.url, protocols || []);
ws.binaryType = this.binaryType;
if (reconnectAttempt) {
if (this.maxReconnectAttempts && this.reconnectAttempts > this.maxReconnectAttempts) {
return;
}
} else {
eventTarget.dispatchEvent(generateEvent('connecting'));
this.reconnectAttempts = 0;
}
if (self.debug || ReconnectingWebSocket.debugAll) {
console.debug('ReconnectingWebSocket', 'attempt-connect', self.url);
}
var localWs = ws;
var timeout = setTimeout(function() {
if (self.debug || ReconnectingWebSocket.debugAll) {
console.debug('ReconnectingWebSocket', 'connection-timeout', self.url);
}
timedOut = true;
localWs.close();
timedOut = false;
}, self.timeoutInterval);
ws.onopen = function(event) {
clearTimeout(timeout);
if (self.debug || ReconnectingWebSocket.debugAll) {
console.debug('ReconnectingWebSocket', 'onopen', self.url);
}
self.protocol = ws.protocol;
self.readyState = WebSocket.OPEN;
self.reconnectAttempts = 0;
var e = generateEvent('open');
e.isReconnect = reconnectAttempt;
reconnectAttempt = false;
eventTarget.dispatchEvent(e);
};
ws.onclose = function(event) {
clearTimeout(timeout);
ws = null;
if (forcedClose) {
self.readyState = WebSocket.CLOSED;
eventTarget.dispatchEvent(generateEvent('close'));
} else {
self.readyState = WebSocket.CONNECTING;
var e = generateEvent('connecting');
e.code = event.code;
e.reason = event.reason;
e.wasClean = event.wasClean;
eventTarget.dispatchEvent(e);
if (!reconnectAttempt && !timedOut) {
if (self.debug || ReconnectingWebSocket.debugAll) {
console.debug('ReconnectingWebSocket', 'onclose', self.url);
}
eventTarget.dispatchEvent(generateEvent('close'));
}
var timeout = self.reconnectInterval * Math.pow(self.reconnectDecay, self.reconnectAttempts);
setTimeout(function() {
self.reconnectAttempts++;
self.open(true);
}, timeout > self.maxReconnectInterval ? self.maxReconnectInterval : timeout);
}
};
ws.onmessage = function(event) {
if (self.debug || ReconnectingWebSocket.debugAll) {
console.debug('ReconnectingWebSocket', 'onmessage', self.url, event.data);
}
var e = generateEvent('message');
e.data = event.data;
eventTarget.dispatchEvent(e);
};
ws.onerror = function(event) {
if (self.debug || ReconnectingWebSocket.debugAll) {
console.debug('ReconnectingWebSocket', 'onerror', self.url, event);
}
eventTarget.dispatchEvent(generateEvent('error'));
};
}
// Whether or not to create a websocket upon instantiation
if (this.automaticOpen == true) {
this.open(false);
}
/**
* Transmits data to the server over the WebSocket connection.
*
* @param data a text string, ArrayBuffer or Blob to send to the server.
*/
this.send = function(data) {
if (ws) {
if (self.debug || ReconnectingWebSocket.debugAll) {
console.debug('ReconnectingWebSocket', 'send', self.url, data);
}
return ws.send(data);
} else {
throw 'INVALID_STATE_ERR : Pausing to reconnect websocket';
}
};
/**
* Closes the WebSocket connection or connection attempt, if any.
* If the connection is already CLOSED, this method does nothing.
*/
this.close = function(code, reason) {
// Default CLOSE_NORMAL code
if (typeof code == 'undefined') {
code = 1000;
}
forcedClose = true;
if (ws) {
ws.close(code, reason);
}
};
/**
* Additional public API method to refresh the connection if still open (close, re-open).
* For example, if the app suspects bad data / missed heart beats, it can try to refresh.
*/
this.refresh = function() {
if (ws) {
ws.close();
}
};
}
/**
* An event listener to be called when the WebSocket connection's readyState changes to OPEN;
* this indicates that the connection is ready to send and receive data.
*/
ReconnectingWebSocket.prototype.onopen = function(event) {};
/** An event listener to be called when the WebSocket connection's readyState changes to CLOSED. */
ReconnectingWebSocket.prototype.onclose = function(event) {};
/** An event listener to be called when a connection begins being attempted. */
ReconnectingWebSocket.prototype.onconnecting = function(event) {};
/** An event listener to be called when a message is received from the server. */
ReconnectingWebSocket.prototype.onmessage = function(event) {};
/** An event listener to be called when an error occurs. */
ReconnectingWebSocket.prototype.onerror = function(event) {};
/**
* Whether all instances of ReconnectingWebSocket should log debug messages.
* Setting this to true is the equivalent of setting all instances of ReconnectingWebSocket.debug to true.
*/
ReconnectingWebSocket.debugAll = false;
ReconnectingWebSocket.CONNECTING = WebSocket.CONNECTING;
ReconnectingWebSocket.OPEN = WebSocket.OPEN;
ReconnectingWebSocket.CLOSING = WebSocket.CLOSING;
ReconnectingWebSocket.CLOSED = WebSocket.CLOSED;
return ReconnectingWebSocket;
});
var Scopes =
{
/** None component scope (nothing will be searched). */
// const SCOPE_NONE = "none";
//
// /** Local component scope. */
// const SCOPE_LOCAL = "local";
//
// /** Component scope. */
// const SCOPE_COMPONENT = "component";
//
// /** Application scope. */
// const SCOPE_APPLICATION = "application";
/** Platform scope. */
SCOPE_PLATFORM: "platform",
/** Global scope. */
SCOPE_GLOBAL: "global",
// /** Parent scope. */
// SCOPE_PARENT:string = "parent";
/** Session scope. */
SCOPE_SESSION: "session"
};
var SUtil =
{
wrappedConversionTypes:
{
java_lang_Integer: "number",
java_lang_Byte: "number",
java_lang_Short: "number",
java_lang_Long: "number",
java_lang_Float: "number",
java_lang_Double: "number",
java_lang_Character: "string",
java_lang_Boolean: "boolean"
},
/**
* Test if an object is a basic type.
* @param obj The object.
* @return True, if is a basic type.
*/
isBasicType: function(obj)
{
return typeof obj !== 'object' || !obj;
},
/**
* Test if an object is a java wrapped type.
* @param obj The object.
* @return False, if is not a wrapped primitive type, else returns the corresponding JS type.
*/
isWrappedType: function(obj)
{
if("__classname" in obj)
{
var searching = obj.__classname.replace(/\./g, '_')
return this.wrappedConversionTypes[searching];
}
else
{
return false;
}
},
/**
* Check of an obj is an enum.
*/
isEnum: function(obj)
{
return ("enum" in obj)
},
/**
* Test if an object is an array.
* @param obj The object.
* @return True, if is an array.
*/
isArray: function(obj)
{
return Object.prototype.toString.call(obj) == '[object Array]';
},
/**
* Compute the approx. size of an object.
* @param obj The object.
*/
sizeOf: function(object)
{
var objects = [object];
var size = 0;
for(var i = 0; i < objects.length; i++)
{
switch(typeof objects[i])
{
case 'boolean':
size += 4;
break;
case 'number':
size += 8;
break;
case 'string':
size += 2 * objects[i].length;
break;
case 'object':
if(Object.prototype.toString.call(objects[i]) != '[object Array]')
{
for(var key in objects[i])
size += 2 * key.length;
}
var processed = false;
var key;
for(key in objects[i])
{
for(var search = 0; search < objects.length; search++)
{
if(objects[search] === objects[i][key])
{
processed = true;
break;
}
}
}
if(!processed)
objects.push(objects[i][key]);
}
}
return size;
},
/**
* Check if object is true by inspecting if it contains a true property.
*/
isTrue: function(obj)
{
return obj == true || (obj != null && obj.hasOwnProperty("value") && obj.value == true);
},
/**
* Assert that throws an error if not holds.
*/
assert: function(condition, message)
{
if(!condition)
{
message = message || "Assertion failed";
if(typeof Error !== "undefined")
{
throw new Error(message);
}
throw message; // Fallback
}
},
/**
* Get the service id as string.
* (otherwise it cannot be used as key in a map because
* no equals exists).
*/
getServiceIdAsString: function(sid)
{
return sid.serviceName+"@"+sid.providerId;
},
/**
* Add a console out error handler to the promise.
*/
addErrHandler: function(p)
{
p.oldcatch = p.catch;
p.hasErrorhandler = false;
p.catch = function(eh)
{
p.hasErrorHandler = true;
return p.oldcatch(eh);
};
p.oldcatch(function(err)
{
if(!p.hasErrorHandler)
console.log("Error occurred: "+err);
});
p.oldthen = p.then;
p.then = function(t, e)
{
if(e)
p.hasErrorHandler = true;
return p.oldthen(t, e);
};
return p;
},
/**
* Test if a number is a float.
* @param n The number to test.
* @return True, if is float.
*/
isFloat: function(n)
{
return n === +n && n !== (n | 0);
},
/**
* Test if a number is an integer.
* @param n The number to test.
* @return True, if is integer.
*/
isInteger: function(n)
{
return n === +n && n === (n | 0);
},
/**
* Check if an object is contained in an array.
* Uses equal function to check equality of objects.
* If not provided uses reference test.
* @param object The object to check.
* @param objects The array.
* @param equals The equals method.
* @return True, if is contained.
*/
containsObject: function(object, objects, equals)
{
var ret = false;
for(var i=0; i
{
// console.log(obj+" "+prop+" "+parent);
if(!SUtil.isBasicType(obj))
{
// test if it is just a placeholder object that must be changed
// if(prop!=null)
// {
for(var i = 0; i < replacemarker.length; i++)
{
if(replacemarker[i] in obj)
{
obj = obj[replacemarker[i]];
break;
}
}
// }
// instantiate classes
if("__classname" in obj)
{
var className = obj["__classname"];
//if(className == "jadex.bridge.service.IService")
if(className == "org.activecomponents.webservice.ServiceInfo")
{
obj = new Jadex.ServiceProxy(obj.serviceIdentifier, recurse(obj.methodNames, "methodNames", obj), url)
}
else if(className in JsonParser.registeredClasses)
{
var func = JsonParser.registeredClasses[className];
if(func.create)
{
obj = func.create(obj);
}
else
{
// iterate members:
var instance = new func();
for(var prop in obj)
{
instance[prop] = recurse(obj[prop], prop, obj);
}
obj = instance;
}
}
}
else
{
// recreate arrays
if(SUtil.isArray(obj))
{
for(var i = 0; i < obj.length; i++)
{
if(!SUtil.isBasicType(obj[i]))
{
if(refmarker in obj[i])
{
obj[i] = recurse(obj[i], i, obj);
}
else
{
obj[i] = recurse(obj[i], prop, obj);
}
}
}
}
}
if(refmarker in obj)
{
var ref = obj[refmarker];
if(ref in os)
{
obj = os[ref];
}
else
{
refs.push([parent, prop, ref]); // lazy evaluation necessary
}
}
else
{
var id = null;
if(idmarker in obj)
{
id = obj[idmarker];
delete obj[idmarker];
}
if("$values" in obj) // an array
{
obj = obj.$values.map(recurse);
}
else
{
for(var prop in obj)
{
obj[prop] = recurse(obj[prop], prop, obj);
}
}
if(id != null)
{
os[id] = obj;
}
}
// unwrap boxed values for JS:
var wrappedType = SUtil.isWrappedType(obj);
if(wrappedType)
{
// console.log("found wrapped: " + isWrappedType(obj) + " for: " + obj.__classname + " with value: " + obj.value)
if(wrappedType == "boolean")
{
// this will not happen, because booleans are already native?
// obj = obj.value == "true"
}
else if(wrappedType == "string")
{
obj = obj.value
}
else
{
// everything else is a number in JS
obj = +obj.value
}
}
else if(SUtil.isEnum(obj))
{
// convert enums to strings
obj = obj.value;
}
}
return obj;
};
obj = recurse(obj, null, null);
// resolve lazy references
for(var i = 0; i < refs.length; i++)
{
var ref = refs[i];
ref[0][ref[1]] = os[ref[2]];
}
return obj;
}
};
JsonParser.init();
var ConnectionHandler =
{
/** The websocket connections. */
connections: [],
baseurl: null,
/** The map of open outcalls. */
outcalls: [],
/** The map of provided services (sid -> service invocation function). */
providedServices: [],
init: function()
{
var scripts = document.getElementsByTagName('script');
var script = scripts[scripts.length - 1];
var prot = SUtil.isSecure()? "wss": "ws";
if(script["src"])
{
this.baseurl = script["src"];
this.baseurl = prot+this.baseurl.substring(this.baseurl.indexOf("://"));
}
else if(script.hasAttributes())
{
//this.baseurl = "ws://" + window.location.hostname + ":" + window.location.port + "/wswebapi";
this.baseurl = prot+"://" + window.location.hostname + ":" + window.location.port + script.attributes.getNamedItem("src").value;
}
else
{
// fail?
throw new Error("Could not find websocket url");
}
this.baseurl = this.baseurl.substring(0, this.baseurl.lastIndexOf("jadex.js")-1);
this.connections[""] = this.addConnection(this.baseurl);
//this.connections[undefined] = this.connections[null];
},
WebsocketCall: function(type, resolve, reject, cb)
{
var self = this;
this.type = type;
this.finished = false;
this.resolve = resolve;
this.reject = reject;
this.cb = cb;
/**
* Resume the listeners of promise.
*/
this.resume = function(result, exception)
{
if(self.cb != null && (exception == null || exception == undefined) && !SUtil.isTrue(self.finished))
{
self.cb(result);
}
else if(SUtil.isTrue(self.finished))
{
exception == null || exception == undefined? self.resolve(result): self.reject(exception);
}
}
},
/**
* Internal function to get a web socket for a url.
*/
getConnection: function(url)
{
if(url == null)
url = "";
var ret = this.connections[url];
if(ret!=null)
{
return ret;
}
else
{
return this.addConnection(url);
}
},
/**
* Add a new server connection.
* @param url The url.
*/
addConnection: function(url)
{
var self = this;
this.connections[url] = new Promise(function(resolve, reject)
{
try
{
//var ws = new WebSocket(url);
var ws = new ReconnectingWebSocket(url);
ws.onopen = () =>
{
resolve(ws);
};
ws.onmessage = message =>
{
self.onMessage(message, url);
};
}
catch(e)
{
reject(e);
}
});
return this.connections[url];
},
/**
* Send a message to the server and create a callid for the answer message.
*/
sendData: function(url, data)
{
this.getConnection(url).then(ws =>
{
ws.send(data);
});
},
/**
* Send a message to the server in an ongoing conversation.
*/
sendConversationMessage: function(url, cmd)
{
this.getConnection(url).then((ws) =>
{
ws.send(JSON.stringify(cmd));
});
},
/**
* Send a message to the server and create a callid for the answer message.
*/
sendMessage: function(url, cmd, type, resolve, reject, callback)
{
// todo: use Jadex binary to serialize message and send
var callid = this.randomString(-1);
this.outcalls[callid] = new this.WebsocketCall(type, resolve, reject, callback);
cmd.callid = callid;
this.sendRawMessage(url, cmd);
return callid;
},
/**
* Send a raw message without callid management.
*/
sendRawMessage: function(url, cmd)
{
if(!cmd.callid)
console.log("Sending message without callid: "+cmd);
var data = this.objectToJson(cmd);
//console.log(data);
//var size = sizeOf(cmd);
var size = data.length;
var limit = 7000; // 8192
// If message is larger than limit slice the message via partial messages
if(size>limit)
{
var cnt = Math.ceil(size/limit);
for(var i=0; i
{
if(value instanceof ArrayBuffer)
{
//var ret = window.btoa(value);
var ret = btoa(String.fromCharCode.apply(null, new Uint8Array(value)));
return ret;
}
else
{
return value;
}
//return value instanceof ArrayBuffer? window.btoa(value): value;
};
return JSON.stringify(object, replacer);
},
/**
* Send a result.
*/
sendResult: function(url, result, finished, callid)
{
var cmd =
{
__classname: "org.activecomponents.webservice.messages.ResultMessage",
callid: callid,
result: result,
finished: finished
};
this.sendRawMessage(url, cmd);
},
/**
* Send an exception.
*/
sendException: function(url, err, finished, callid)
{
var exception =
{
__classname: "java.lang.RuntimeException",
message: ""+err
}
var cmd =
{
__classname: "org.activecomponents.webservice.messages.ResultMessage",
callid: callid,
exception: exception,
finished: finished
};
this.sendRawMessage(url, cmd);
},
/**
* Called when a message arrives.
*/
onMessage: function(message, url)
{
if(message.type == "message")
{
var msg = JsonParser.parse(message.data, url);
var call = this.outcalls[msg.callid];
// console.log("outcalls: "+outcalls);
if(call!=null)
{
if(SUtil.isTrue(msg.finished))
{
delete this.outcalls[msg.callid];
// console.log("outCall deleted: "+msg.callid);
call.finished = true;
}
if(call.type=="search")
{
if(msg.result!=null)
{
if(msg.result.hasOwnProperty("__array"))
msg.result = msg.result.__array;
if(msg.result.hasOwnProperty("__collection"))
msg.result[1] = msg.result[1].__collection;
}
var serproxy;
if(msg.exception==null && msg.result!=null)
{
serproxy = msg.result;//createServiceProxy(msg.result[0], msg.result[1]);
}
call.resume(serproxy, msg.exception);
}
else if(call.type=="invoke")
{
call.resume(msg.result, msg.exception);
}
else if(outCall.type=="provide")
{
if(msg.exception!=null)
{
call.reject(msg.exception);
}
else
{
// Save the service functionality in the inca
this.providedServices[SUtil.getServiceIdAsString(msg.result)] = call.cb;
call.resolve(msg.result);
}
}
else if(call.type=="unprovide")
{
if(msg.exception!=null)
{
call.reject(msg.exception);
}
else
{
// removeProperty?!
this.providedServices[SUtil.getServiceIdAsString(msg.result)] = null;
call.resolve(msg.result);
}
}
}
else // incoming call
{
if(msg.__classname==="org.activecomponents.webservice.messages.ServiceInvocationMessage")
{
var service = this.providedServices[SUtil.getServiceIdAsString(msg.serviceId)];
if(service)
{
var res;
// If it a service object with functions or just a function
if(service[msg.methodName])
{
//res = service[msg.methodName](msg.parameterValues);
res = service[msg.methodName].apply(undefined, msg.parameterValues);
}
// If it is just a function (assume functional interface as in Java)
else if(typeof res==="function")
{
//res = service(msg.parameterValues);
res = service.apply(undefined, msg.parameterValues);
}
// If it is an invocation handler with a generic invoke method
else if(service.invoke)
{
res = service.invoke(msg.methodName, msg.parameterValues);
}
else
{
console.log("Cannot invoke service method (not found): "+msg.methodName);
}
// Hack, seems to loose this in callback :-(
// var fthis = this;
// Make anything that comes back to a promise
// Promise.resolve(res).then(function(res)
// {
// fthis.sendResult(url, res, true, msg.callid);
// })
// .catch(function(e)
// {
// fthis.sendException(url, e, true, msg.callid);
// });
Promise.resolve(res).then(res =>
{
this.sendResult(url, res, true, msg.callid);
})
.catch(e =>
{
this.sendException(url, e, true, msg.callid);
});
}
else
{
console.log("Provided service not found: "+[msg.serviceId]);
this.sendException(url, "Provided service not found: "+[msg.serviceId], true, msg.callid);
}
}
else
{
console.log("Received message without request: "+msg);
}
}
}
else if(message.type == "binary")
{
console.log("Binary messages currently not supported");
}
// else: do not handle pong messages
},
/**
* Create a random string.
* @param length The length of the string.
* @returns The random string.
*/
randomString: function(length)
{
if(length<1)
length = 10;
return Math.round((Math.pow(36, length + 1) - Math.random() * Math.pow(36, length))).toString(36).slice(1);
}
};
ConnectionHandler.init();
var Jadex =
{
/**
* Service Proxy constructor function.
*/
ServiceProxy: function(serviceid, methodnames, url)
{
var outer = this;
this.serviceid = serviceid;
//this.methodnames = methodnames;
//this.url = url;
/**
* Create method function (needed to preserve the name).
*
* Creates an argument array and invokes generic invoke method.
*
* TODO: callback function hack!
*/
createMethod = function(name)
{
return function ()
{
var params = [];
var callback;
for(var j = 0; j < arguments.length; j++)
{
if(typeof arguments[j] === "function")
{
callback = arguments[j];
}
else
{
params.push(arguments[j]);
}
}
return outer.invoke(name, params, callback);
}
}
for(var i = 0; i < methodnames.length; i++)
{
this[methodnames[i]] = createMethod(methodnames[i]);
}
/**
* Generic invoke method that sends a method call to the server side.
*/
this.invoke = function(name, params, callback)
{
var ret = new Jadex.JadexPromise(this.url);
// Convert parameters seperately, one by one
var cparams = [];
for(var i=0; i
{
// console.log("calling intermediate result with: " + intermediateResult);
ret.resolveIntermediate(res);
if(callback)
callback(res);
};
ret.callid = ConnectionHandler.sendMessage(this.url, cmd, "invoke", res => ret.resolve(res), ex => ret.reject(ex), wrapcb);
return ret;
}
},
JadexPromise: function(resolveFunc, rejectFunc, callid)
{
this.resolveFunc = resolveFunc;
this.rejectFunc = rejectFunc;
this.intermediateResolveCallbacks = [];
this.callid = callid;
this.promise = new Promise((resolve, reject) =>
{
this.resolveFunc = resolve;
this.rejectFunc = reject;
});
this.then = function(onfulfilled, onrejected)
{
return this.promise.then(onfulfilled, onrejected);
};
this.resolve = function(value)
{
// return this.promise.resolve(value);
return this.resolveFunc(value);
};
this.reject = function(error)
{
// return this.promise.reject(error);
return this.rejectFunc(error);
};
this.resolveIntermediate = function(value)
{
for(var cb of this.intermediateResolveCallbacks)
{
cb(value);
}
};
this.thenIntermediate = function(onfulfilled, onrejected)//?: (value: T)=>(PromiseLike|TResult), onrejected?: (reason: any)=>(PromiseLike|TResult))
{
this.intermediateResolveCallbacks.push(onfulfilled);
// this.intermediateRejectCallbacks.push(onrejected);
};
this.terminate = function()
{
var cmd =
{
__classname: "org.activecomponents.webservice.messages.ServiceTerminateInvocationMessage",
callid: this.callid
};
ConnectionHandler.sendConversationMessage(this.url, cmd);
};
this.pull = function()
{
var cmd =
{
__classname: "org.activecomponents.webservice.messages.PullResultMessage",
callid: this.callid
};
ConnectionHandler.sendConversationMessage(this.url, cmd);
};
},
ServiceSearchMessage: function(type, multiple, scope)
{
this.__classname = "org.activecomponents.webservice.messages.ServiceSearchMessage";
//this.callid = callid;
this.type = type;
this.multiple = multiple;
this.scope = scope;
},
ServiceInvocationMessage: function(serviceid, methodname, parametervalues)
{
this.__classname = "org.activecomponents.webservice.messages.ServiceInvocationMessage";
this.serviceId = serviceid;
this.methodName = methodname;
this.parameterValues = parametervalues;
},
ServiceUnprovideMessage: function(serviceid)
{
this.__classname = "org.activecomponents.webservice.messages.ServiceUnprovideMessage";
this.serviceId = serviceid;
},
PartialMessage: function(callid, data, number, count)
{
this.__classname = "org.activecomponents.webservice.messages.PartialMessage";
this.callid = callid;
this.data = data;
this.number = number;
this.count = count;
},
ServiceProvideMessage: function(type, scope, tags)
{
this.__classname = "org.activecomponents.webservice.messages.ServiceProvideMessage";
this.type = type;
this.scope = scope;
this.tags = tags;
},
/**
* Get a service from a publication point.
* @param type The service type.
* @param scope The scope.
* @param url The url of the websocket.
*/
getService: function(type, scope, url)
{
var self = this;
var prom = SUtil.addErrHandler(new Promise((resolve, reject) =>
{
var cmd = new self.ServiceSearchMessage(type, false, scope != null ? scope : Scopes.SCOPE_PLATFORM);
ConnectionHandler.sendMessage(url, cmd, "search", resolve, reject, null);
}));
return prom;
},
/**
* Get services from a publication point.
* @param type The service type.
* @param callback The callback function for the intermediate results.
* @param scope The search scope.
* @param url The url of the websocket.
*/
getServices: function(type, callback, scope, url)
{
var self = this;
SUtil.assert(callback instanceof Function && callback != null);
var prom = SUtil.addErrHandler(new Promise((resolve, reject) =>
{
var cmd = new self.ServiceSearchMessage(type, true, scope != null ? scope : Scopes.SCOPE_PLATFORM);
ConnectionHandler.sendMessage(url, cmd, "search", resolve, reject, callback);
}));
return prom;
},
/**
* Provide a new (client) service.
* @param type The service type.
* @param scope The provision scope.
* @param url The url of the websocket.
*/
provideService: function(type, scope, tags, callback, url)
{
var self = this;
return SUtil.addErrHandler(new Promise(function(resolve, reject)
{
var cmd = new self.ServiceProvideMessage(type, scope!=null? scope: "global", typeof tags === "string"? [tags]: tags);
ConnectionHandler.sendMessage(url, cmd, "provide", resolve, reject, callback);
}));
},
/**
* Unprovide a (client) service.
* @param type The service type.
* @param scope The provision scope.
* @param url The url of the websocket.
*/
unprovideService: function(sid, url)
{
var self = this;
return SUtil.addErrHandler(new Promise(function(resolve, reject)
{
var cmd = new self.ServiceUnprovideMessage(sid);
ConnectionHandler.sendMessage(url, cmd, "unprovide", resolve, reject, null);
}));
},
/**
* Register a class for json (de)serialization.
*/
registerClass: function(clazz)
{
JsonParser.registerClass(clazz);
}
};
var jadex = Jadex;
© 2015 - 2024 Weber Informatics LLC | Privacy Policy