diff -r f11b234497f7 -r 61c384dda19e src/js/libs/tracemanager.js --- a/src/js/libs/tracemanager.js Fri Apr 27 19:18:21 2012 +0200 +++ b/src/js/libs/tracemanager.js Thu May 03 17:52:52 2012 +0200 @@ -1,512 +1,540 @@ -/* - * Modelled Trace API - */ -IriSP.TraceManager = function($) { - // If there are more than MAX_FAILURE_COUNT synchronisation - // failures, then disable synchronisation - MAX_FAILURE_COUNT = 20; - - // If there are more than MAX_BUFFER_SIZE obsels in the buffer, - // then "compress" them as a single "ktbsFullBuffer" - MAX_BUFFER_SIZE = 500; - - var BufferedService_prototype = { - /* - * Buffered service for traces - */ - // url: "", - // buffer: [], - // isReady: false, - // timer: null, - // failureCount: 0, - - /* Flush buffer */ - flush: function() { - // FIXME: add mutex on this.buffer - if (! this.isReady) - { - if (window.console) window.console.log("Sync service not ready"); - } else if (this.failureCount > MAX_FAILURE_COUNT) - { - // Disable synchronisation - this.set_sync_mode('none'); - } else if (this.buffer.length) { - var temp = this.buffer; - this.buffer = []; - - if (this.mode == 'GET') - { - // GET mode: do some data mangline. We mark the - // "compressed" nature of the generated JSON by - // prefixing it with c - var data = 'c' + JSON.stringify(temp.map(function (o) { return o.toCompactJSON(); })); - // Swap " (very frequent, which will be - // serialized into %22) and ; (rather rare), this - // saves some bytes - data = data.replace(/[;"]/g, function(s){ return s == ';' ? '"' : ';'; }).replace(/#/g, '%23'); - // FIXME: check data length (< 2K is safe) - var request=$('').error( function() { this.failureCount += 1; }) - .load( function() { this.failureCount = 0; }) - .attr('src', this.url + 'trace/?data=' + data); - } - else - { - $.ajax({ url: this.url + 'trace/', - type: 'POST', - contentType: 'application/json', - data: JSON.stringify(temp.map(function (o) { return o.toJSON(); })), - processData: false, - // Type of the returned data. - dataType: "html", - error: function(jqXHR, textStatus, errorThrown) { - if (window.console) window.console.log("Error when sending buffer:", textStatus); - this.failureCount += 1; - }, - success: function(data, textStatus, jqXHR) { - // Reset failureCount to 0 as soon as there is 1 valid answer - this.failureCount = 0; - } - }); - } - } - }, - - /* Sync mode: delayed, sync (immediate sync), none (no - * synchronisation with server, the trace has to be explicitly saved - * if needed */ - set_sync_mode: function(mode) { - this.sync_mode = mode; - if (! this.isReady && mode !== "none") - this.init(); - if (mode == 'delayed') { - this.start_timer(); - } else { - this.stop_timer(); - } - }, - - /* Enqueue an obsel */ - enqueue: function(obsel) { - if (this.buffer.length > MAX_BUFFER_SIZE) - { - obsel = new Obsel('ktbsFullBuffer', this.buffer[0].begin, - this.buffer[this.buffer.length - 1].end, this.buffer[0].subject); - obsel.trace = this.buffer[0].trace; - this.buffer = []; - } - this.buffer.push(obsel); - if (this.sync_mode === 'sync') { - // Immediate sync of the obsel. - this.flush(); - } - }, - - start_timer: function() { - var self = this; - if (this.timer === null) { - this.timer = window.setInterval(function() { - self.flush(); - }, this.timeOut); - } - }, - - stop_timer: function() { - if (this.timer !== null) { - window.clearInterval(this.timer); - this.timer = null; - } - }, - - /* - * Initialize the sync service - */ - init: function() { - var self = this; - if (this.isReady) - /* Already initialized */ - return; - if (this.mode == 'GET') - { - var request=$('').attr('src', this.url + 'login?userinfo={"name":"ktbs4js"}'); - // Do not wait for the return, assume it is - // initialized. This assumption will not work anymore - // if login returns some necessary information - this.isReady = true; - } - else - { - $.ajax({ url: this.url + 'login', - type: 'POST', - data: 'userinfo={"name":"ktbs4js"}', - success: function(data, textStatus, jqXHR) { - self.isReady = true; - if (self.buffer.length) { - self.flush(); - } - } - }); - } - } - }; - var BufferedService = function(url, mode) { - this.url = url; - this.buffer = []; - this.isReady = false; - this.timer = null; - this.failureCount = 0; - // sync_mode is either "none", "sync" or "buffered" - this.sync_mode = "none"; - /* mode can be either POST or GET */ - if (mode == 'POST' || mode == 'GET') - this.mode = mode; - else - this.mode = 'POST'; - /* Flush buffer every timeOut ms if the sync_mode is delayed */ - this.timeOut = 2000; - }; - BufferedService.prototype = BufferedService_prototype; - - var Trace_prototype = { - /* FIXME: We could/should use a sorted list such as - http://closure-library.googlecode.com/svn/docs/class_goog_structs_AvlTree.html - to speed up queries based on time */ - obsels: [], - /* Trace URI */ - uri: "", - default_subject: "", - /* baseuri is used as the base URI to resolve relative - * attribute-type names in obsels. Strictly speaking, this - * should rather be expressed as a reference to model, or - * more generically, as a qname/URI dict */ - baseuri: "", - /* Mapping of obsel type or property name to a compact - * representation (shorthands). - */ - shorthands: null, - syncservice: null, - - /* Define the trace URI */ - set_uri: function(uri) { - this.uri = uri; - }, - - /* Sync mode: delayed, sync (immediate sync), none (no - * synchronisation with server, the trace has to be explicitly saved - * if needed */ - set_sync_mode: function(mode) { - if (this.syncservice !== null) { - this.syncservice.set_sync_mode(mode); - } - }, - - /* - * Return a list of the obsels of this trace matching the parameters - */ - list_obsels: function(_begin, _end, _reverse) { - var res; - if (typeof _begin !== 'undefined' || typeof _end !== 'undefined') { - /* - * Not optimized yet. - */ - res = []; - var l = this.obsels.length; - for (var i = 0; i < l; i++) { - var o = this.obsels[i]; - if ((typeof _begin !== 'undefined' && o.begin > _begin) && (typeof _end !== 'undefined' && o.end < _end)) { - res.push(o); - } - } - } - - if (typeof _reverse !== 'undefined') { - if (res !== undefined) { - /* Should reverse the whole list. Make a copy. */ - res = this.obsels.slice(0); - } - res.sort(function(a, b) { return b.begin - a.begin; }); - return res; - } - - if (res === undefined) { - res = this.obsels; - } - return res; - - }, - - /* - * Return the obsel of this trace identified by the URI, or undefined - */ - get_obsel: function(id) { - for (var i = 0; i < this.obsels.length; i++) { - /* FIXME: should check against variations of id/uri, take this.baseuri into account */ - if (this.obsels[i].uri === id) { - return this.obsels[i]; - } - } - return undefined; - }, - - set_default_subject: function(subject) { - this.default_subject = subject; - }, - - get_default_subject: function() { - return this.default_subject; - }, - - /* (type:ObselType, begin:int, end:int?, subject:str?, attributes:[AttributeType=>any]?) */ - /* Create a new obsel and add it to the trace */ - create_obsel: function(type, begin, end, subject, _attributes) { - var o = new Obsel(type, begin, end, subject); - if (typeof _attributes !== 'undefined') { - o.attributes = _attributes; - } - o.trace = this; - this.obsels.push(o); - if (this.syncservice !== null) - this.syncservice.enqueue(o); - }, - - /* Helper methods */ - - /* Create a new obsel with the given attributes */ - trace: function(type, _attributes, _begin, _end, _subject) { - var t = (new Date()).getTime(); - if (typeof begin === 'undefined') { - _begin = t; - } - if (typeof end === 'undefined') { - _end = _begin; - } - if (typeof subject === 'undefined') { - _subject = this.default_subject; - } - if (typeof _attributes === 'undefined') { - _attributes = {}; - } - return this.create_obsel(type, _begin, _end, _subject, _attributes); - } - }; - - var Trace = function(uri, requestmode) { - /* FIXME: We could/should use a sorted list such as - http://closure-library.googlecode.com/svn/docs/class_goog_structs_AvlTree.html - to speed up queries based on time */ - this.obsels = []; - /* Trace URI */ - if (uri === undefined) - uri = ""; - this.uri = uri; - this.sync_mode = "none"; - this.default_subject = ""; - this.shorthands = {}; - /* baseuri is used a the base URI to resolve relative attribute names in obsels */ - this.baseuri = ""; - - this.syncservice = new BufferedService(uri, requestmode); - $(window).unload( function () { - if (this.syncservice && this.sync_mode !== 'none') { - this.syncservice.flush(); - this.syncservice.stop_timer(); - } - }); - }; - Trace.prototype = Trace_prototype; - - var Obsel_prototype = { - /* The following attributes are here for documentation - * purposes. They MUST be defined in the constructor - * function. */ - trace: undefined, - type: undefined, - begin: undefined, - end: undefined, - subject: undefined, - /* Dictionary indexed by ObselType URIs */ - attributes: {}, - - /* Method definitions */ - get_trace: function() { - return this.trace; - }, - - get_obsel_type: function() { - return this.type; - }, - get_begin: function() { - return this.begin; - }, - get_end: function() { - return this.end; - }, - get_subject: function() { - return this.subject; - }, - - list_attribute_types: function() { - var result = []; - for (var prop in this.attributes) { - if (this.hasOwnProperty(prop)) - result.push(prop); - } - /* FIXME: we return URIs here instead of AttributeType elements */ - return result; - }, - - list_relation_types: function() { - /* FIXME: not implemented yet */ - }, - - list_related_obsels: function (rt) { - /* FIXME: not implemented yet */ - }, - list_inverse_relation_types: function () { - /* FIXME: not implemented yet */ - }, - list_relating_obsels: function (rt) { - /* FIXME: not implemented yet */ - }, - /* - * Return the value of the given attribute type for this obsel - */ - get_attribute_value: function(at) { - if (typeof at === "string") - /* It is a URI */ - return this.attributes[at]; - else - /* FIXME: check that at is instance of AttributeType */ - return this.attributes[at.uri]; - }, - - - /* obsel modification (trace amendment) */ - - set_attribute_value: function(at, value) { - if (typeof at === "string") - /* It is a URI */ - this.attributes[at] = value; - /* FIXME: check that at is instance of AttributeType */ - else - this.attributes[at.uri] = value; - }, - - del_attribute_value: function(at) { - if (typeof at === "string") - /* It is a URI */ - delete this.attributes[at]; - /* FIXME: check that at is instance of AttributeType */ - else - delete this.attributes[at.uri]; - }, - - add_related_obsel: function(rt, value) { - /* FIXME: not implemented yet */ - }, - - del_related_obsel: function(rt, value) { - /* FIXME: not implemented yet */ - }, - - /* - * Return a JSON representation of the obsel - */ - toJSON: function() { - var r = { - "@id": this.id, - "@type": this.type, - "begin": this.begin, - "end": this.end, - "subject": this.subject - }; - for (var prop in this.attributes) { - if (this.hasOwnProperty(prop)) - r[prop] = this.attributes[prop]; - } - return r; - }, - - /* - * Return a compact JSON representation of the obsel. - * Use predefined + custom shorthands for types/properties - */ - toCompactJSON: function() { - var r = { - "@i": this.id, - "@t": (this.trace.shorthands.hasOwnProperty(this.type) ? this.trace.shorthands[this.type] : this.type), - "@b": this.begin, - "@s": this.subject - }; - // Store duration (to save some bytes) and only if it is non-null - if (this.begin !== this.end) - r["@d"] = this.end - this.begin; - - for (var prop in this.attributes) { - if (this.hasOwnProperty(prop)) - { - var v = this.attributes[prop]; - r[prop] = this.trace.shorthands.hasOwnProperty(v) ? this.trace.shorthands[v] : v; - } - } - return r; - }, - - toJSONstring: function() { - return JSON.stringify(this.toJSON()); - } - }; - - var Obsel = function(type, begin, end, subject, attributes) { - this.trace = undefined; - this.uri = ""; - this.id = ""; - this.type = type; - this.begin = begin; - this.end = end; - this.subject = subject; - /* Is the obsel synched with the server ? */ - this.sync_status = false; - /* Dictionary indexed by ObselType URIs */ - this.attributes = {}; - }; - Obsel.prototype = Obsel_prototype; - - var TraceManager_prototype = { - traces: [], - /* - * Return the trace with id name - * If it was not registered, return undefined. - */ - get_trace: function(name) { - return this.traces[name]; - }, - - /* - * Explicitly create and initialize a new trace with the given name. - * The optional uri parameter allows to initialize the trace URI. - * - * If another existed with the same name before, then it is replaced by a new one. - */ - init_trace: function(name, params) - { - if (window.console) window.console.log("init_trace", params); - url = params.url ? params.url : ""; - requestmode = params.requestmode ? params.requestmode : "POST"; - syncmode = params.syncmode ? params.syncmode : "none"; - default_subject = params.default_subject ? params.default_subject : "default"; - var t = new Trace(url, requestmode); - t.set_sync_mode(syncmode); - t.set_default_subject(default_subject); - this.traces[name] = t; - return t; - } - }; - - var TraceManager = function() { - this.traces = {}; - }; - TraceManager.prototype = TraceManager_prototype; - - var tracemanager = new TraceManager(); - return tracemanager; - }; +/* + * Modelled Trace API + * + * This file is part of ktbs4js. + * + * ktbs4js is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * ktbs4js is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with ktbs4js. If not, see . + * + */ +/* FIXME: properly use require.js feature. This will do for debugging in the meantime */ +window.tracemanager = (function($) { + // If there are more than MAX_FAILURE_COUNT synchronisation + // failures, then disable synchronisation + MAX_FAILURE_COUNT = 20; + + // If there are more than MAX_BUFFER_SIZE obsels in the buffer, + // then "compress" them as a single "ktbsFullBuffer" + MAX_BUFFER_SIZE = 500; + + var BufferedService_prototype = { + /* + * Buffered service for traces + */ + // url: "", + // buffer: [], + // isReady: false, + // timer: null, + // failureCount: 0, + + /* Flush buffer */ + flush: function() { + // FIXME: add mutex on this.buffer + if (! this.isReady) + { + if (window.console) window.console.log("Sync service not ready"); + } else if (this.failureCount > MAX_FAILURE_COUNT) + { + // Disable synchronisation + this.set_sync_mode('none'); + } else if (this.buffer.length) { + var temp = this.buffer; + this.buffer = []; + + if (this.mode == 'GET') + { + // GET mode: do some data mangline. We mark the + // "compressed" nature of the generated JSON by + // prefixing it with c + var data = 'c' + JSON.stringify(temp.map(function (o) { return o.toCompactJSON(); })); + // Swap " (very frequent, which will be + // serialized into %22) and ; (rather rare), this + // saves some bytes + data = data.replace(/[;"#]/g, function(s){ return s == ';' ? '"' : ( s == '"' ? ';' : '%23'); }); + // FIXME: check data length (< 2K is safe) + var request=$('').error( function() { this.failureCount += 1; }) + .load( function() { this.failureCount = 0; }) + .attr('src', this.url + 'trace/?data=' + data); + } + else + { + $.ajax({ url: this.url + 'trace/', + type: 'POST', + contentType: 'application/json', + data: JSON.stringify(temp.map(function (o) { return o.toJSON(); })), + processData: false, + // Type of the returned data. + dataType: "html", + error: function(jqXHR, textStatus, errorThrown) { + if (window.console) window.console.log("Error when sending buffer:", textStatus); + this.failureCount += 1; + }, + success: function(data, textStatus, jqXHR) { + // Reset failureCount to 0 as soon as there is 1 valid answer + this.failureCount = 0; + } + }); + } + } + }, + + /* Sync mode: delayed, sync (immediate sync), none (no + * synchronisation with server, the trace has to be explicitly saved + * if needed */ + set_sync_mode: function(mode, default_subject) { + this.sync_mode = mode; + if (! this.isReady && mode !== "none") + this.init(default_subject); + if (mode == 'delayed') { + this.start_timer(); + } else { + this.stop_timer(); + } + }, + + /* Enqueue an obsel */ + enqueue: function(obsel) { + if (this.buffer.length > MAX_BUFFER_SIZE) + { + obsel = new Obsel('ktbsFullBuffer', this.buffer[0].begin, + this.buffer[this.buffer.length - 1].end, this.buffer[0].subject); + obsel.trace = this.buffer[0].trace; + this.buffer = []; + } + this.buffer.push(obsel); + if (this.sync_mode === 'sync') { + // Immediate sync of the obsel. + this.flush(); + } + }, + + start_timer: function() { + var self = this; + if (this.timer === null) { + this.timer = window.setInterval(function() { + self.flush(); + }, this.timeOut); + } + }, + + stop_timer: function() { + if (this.timer !== null) { + window.clearInterval(this.timer); + this.timer = null; + } + }, + + /* + * Initialize the sync service + */ + init: function(default_subject) { + var self = this; + if (this.isReady) + /* Already initialized */ + return; + if (typeof default_subject === 'undefined') + default_subject = 'anonymous'; + if (this.mode == 'GET') + { + var request=$('').attr('src', this.url + 'login?userinfo={"default_subject": "' + default_subject + '"}'); + // Do not wait for the return, assume it is + // initialized. This assumption will not work anymore + // if login returns some necessary information + this.isReady = true; + } + else + { + $.ajax({ url: this.url + 'login', + type: 'POST', + data: 'userinfo={"default_subject":"' + default_subject + '"}', + success: function(data, textStatus, jqXHR) { + self.isReady = true; + if (self.buffer.length) { + self.flush(); + } + } + }); + } + } + }; + var BufferedService = function(url, mode) { + this.url = url; + this.buffer = []; + this.isReady = false; + this.timer = null; + this.failureCount = 0; + // sync_mode is either "none", "sync" or "buffered" + this.sync_mode = "none"; + /* mode can be either POST or GET */ + if (mode == 'POST' || mode == 'GET') + this.mode = mode; + else + this.mode = 'POST'; + /* Flush buffer every timeOut ms if the sync_mode is delayed */ + this.timeOut = 2000; + }; + BufferedService.prototype = BufferedService_prototype; + + var Trace_prototype = { + /* FIXME: We could/should use a sorted list such as + http://closure-library.googlecode.com/svn/docs/class_goog_structs_AvlTree.html + to speed up queries based on time */ + obsels: [], + /* Trace URI */ + uri: "", + default_subject: "", + /* baseuri is used as the base URI to resolve relative + * attribute-type names in obsels. Strictly speaking, this + * should rather be expressed as a reference to model, or + * more generically, as a qname/URI dict */ + baseuri: "", + /* Mapping of obsel type or property name to a compact + * representation (shorthands). + */ + shorthands: null, + syncservice: null, + + /* Define the trace URI */ + set_uri: function(uri) { + this.uri = uri; + }, + + /* Sync mode: delayed, sync (immediate sync), none (no + * synchronisation with server, the trace has to be explicitly saved + * if needed */ + set_sync_mode: function(mode) { + if (this.syncservice !== null) { + this.syncservice.set_sync_mode(mode, this.default_subject); + } + }, + + /* + * Return a list of the obsels of this trace matching the parameters + */ + list_obsels: function(_begin, _end, _reverse) { + var res; + if (typeof _begin !== 'undefined' || typeof _end !== 'undefined') { + /* + * Not optimized yet. + */ + res = []; + var l = this.obsels.length; + for (var i = 0; i < l; i++) { + var o = this.obsels[i]; + if ((typeof _begin !== 'undefined' && o.begin > _begin) && (typeof _end !== 'undefined' && o.end < _end)) { + res.push(o); + } + } + } + + if (typeof _reverse !== 'undefined') { + if (res !== undefined) { + /* Should reverse the whole list. Make a copy. */ + res = this.obsels.slice(0); + } + res.sort(function(a, b) { return b.begin - a.begin; }); + return res; + } + + if (res === undefined) { + res = this.obsels; + } + return res; + + }, + + /* + * Return the obsel of this trace identified by the URI, or undefined + */ + get_obsel: function(id) { + for (var i = 0; i < this.obsels.length; i++) { + /* FIXME: should check against variations of id/uri, take this.baseuri into account */ + if (this.obsels[i].uri === id) { + return this.obsels[i]; + } + } + return undefined; + }, + + set_default_subject: function(subject) { + // FIXME: if we call this method after the sync_service + // init method, then the default_subject will not be + // consistent anymore. Maybe we should then call init() again? + this.default_subject = subject; + }, + + get_default_subject: function() { + return this.default_subject; + }, + + /* (type:ObselType, begin:int, end:int?, subject:str?, attributes:[AttributeType=>any]?) */ + /* Create a new obsel and add it to the trace */ + create_obsel: function(type, begin, end, subject, _attributes) { + var o = new Obsel(type, begin, end, subject); + if (typeof _attributes !== 'undefined') { + o.attributes = _attributes; + } + o.trace = this; + this.obsels.push(o); + if (this.syncservice !== null) + this.syncservice.enqueue(o); + }, + + /* Helper methods */ + + /* Create a new obsel with the given attributes */ + trace: function(type, _attributes, _begin, _end, _subject) { + var t = (new Date()).getTime(); + if (typeof begin === 'undefined') { + _begin = t; + } + if (typeof end === 'undefined') { + _end = _begin; + } + if (typeof subject === 'undefined') { + _subject = this.default_subject; + } + if (typeof _attributes === 'undefined') { + _attributes = {}; + } + return this.create_obsel(type, _begin, _end, _subject, _attributes); + } + }; + + var Trace = function(uri, requestmode) { + /* FIXME: We could/should use a sorted list such as + http://closure-library.googlecode.com/svn/docs/class_goog_structs_AvlTree.html + to speed up queries based on time */ + this.obsels = []; + /* Trace URI */ + if (uri === undefined) + uri = ""; + this.uri = uri; + this.sync_mode = "none"; + this.default_subject = ""; + this.shorthands = {}; + /* baseuri is used a the base URI to resolve relative attribute names in obsels */ + this.baseuri = ""; + + this.syncservice = new BufferedService(uri, requestmode); + $(window).unload( function () { + if (this.syncservice && this.sync_mode !== 'none') { + this.syncservice.flush(); + this.syncservice.stop_timer(); + } + }); + }; + Trace.prototype = Trace_prototype; + + var Obsel_prototype = { + /* The following attributes are here for documentation + * purposes. They MUST be defined in the constructor + * function. */ + trace: undefined, + type: undefined, + begin: undefined, + end: undefined, + subject: undefined, + /* Dictionary indexed by ObselType URIs */ + attributes: {}, + + /* Method definitions */ + get_trace: function() { + return this.trace; + }, + + get_obsel_type: function() { + return this.type; + }, + get_begin: function() { + return this.begin; + }, + get_end: function() { + return this.end; + }, + get_subject: function() { + return this.subject; + }, + + list_attribute_types: function() { + var result = []; + for (var prop in this.attributes) { + if (this.attributes.hasOwnProperty(prop)) + result.push(prop); + } + /* FIXME: we return URIs here instead of AttributeType elements */ + return result; + }, + + list_relation_types: function() { + /* FIXME: not implemented yet */ + }, + + list_related_obsels: function (rt) { + /* FIXME: not implemented yet */ + }, + list_inverse_relation_types: function () { + /* FIXME: not implemented yet */ + }, + list_relating_obsels: function (rt) { + /* FIXME: not implemented yet */ + }, + /* + * Return the value of the given attribute type for this obsel + */ + get_attribute_value: function(at) { + if (typeof at === "string") + /* It is a URI */ + return this.attributes[at]; + else + /* FIXME: check that at is instance of AttributeType */ + return this.attributes[at.uri]; + }, + + + /* obsel modification (trace amendment) */ + + set_attribute_value: function(at, value) { + if (typeof at === "string") + /* It is a URI */ + this.attributes[at] = value; + /* FIXME: check that at is instance of AttributeType */ + else + this.attributes[at.uri] = value; + }, + + del_attribute_value: function(at) { + if (typeof at === "string") + /* It is a URI */ + delete this.attributes[at]; + /* FIXME: check that at is instance of AttributeType */ + else + delete this.attributes[at.uri]; + }, + + add_related_obsel: function(rt, value) { + /* FIXME: not implemented yet */ + }, + + del_related_obsel: function(rt, value) { + /* FIXME: not implemented yet */ + }, + + /* + * Return a JSON representation of the obsel + */ + toJSON: function() { + var r = { + "@id": this.id, + "@type": this.type, + "begin": this.begin, + "end": this.end, + "subject": this.subject + }; + for (var prop in this.attributes) { + if (this.attributes.hasOwnProperty(prop)) + r[prop] = this.attributes[prop]; + } + return r; + }, + + /* + * Return a compact JSON representation of the obsel. + * Use predefined + custom shorthands for types/properties + */ + toCompactJSON: function() { + var r = { + "@t": (this.trace.shorthands.hasOwnProperty(this.type) ? this.trace.shorthands[this.type] : this.type), + "@b": this.begin, + }; + // Transmit subject only if different from default_subject + if (this.subject !== this.trace.default_subject) + r["@s"] = this.subject; + + // Store duration (to save some bytes) and only if it is non-null + if (this.begin !== this.end) + r["@d"] = this.end - this.begin; + + // Store id only if != "" + if (this.id !== "") + r["@i"] = this.id; + + for (var prop in this.attributes) { + if (this.attributes.hasOwnProperty(prop)) + { + var v = this.attributes[prop]; + r[prop] = this.trace.shorthands.hasOwnProperty(v) ? this.trace.shorthands[v] : v; + } + } + return r; + }, + + toJSONstring: function() { + return JSON.stringify(this.toJSON()); + } + }; + + var Obsel = function(type, begin, end, subject, attributes) { + this.trace = undefined; + this.uri = ""; + this.id = ""; + this.type = type; + this.begin = begin; + this.end = end; + this.subject = subject; + /* Is the obsel synched with the server ? */ + this.sync_status = false; + /* Dictionary indexed by ObselType URIs */ + this.attributes = {}; + }; + Obsel.prototype = Obsel_prototype; + + var TraceManager_prototype = { + traces: [], + /* + * Return the trace with id name + * If it was not registered, return undefined. + */ + get_trace: function(name) { + return this.traces[name]; + }, + + /* + * Explicitly create and initialize a new trace with the given name. + * The optional uri parameter allows to initialize the trace URI. + * + * If another existed with the same name before, then it is replaced by a new one. + */ + init_trace: function(name, params) + { + if (window.console) window.console.log("init_trace", params); + url = params.url ? params.url : ""; + requestmode = params.requestmode ? params.requestmode : "POST"; + syncmode = params.syncmode ? params.syncmode : "none"; + default_subject = params.default_subject ? params.default_subject : "default"; + var t = new Trace(url, requestmode); + t.set_default_subject(default_subject); + t.set_sync_mode(syncmode); + this.traces[name] = t; + return t; + } + }; + + var TraceManager = function() { + this.traces = {}; + }; + TraceManager.prototype = TraceManager_prototype; + + var tracemanager = new TraceManager(); + return tracemanager; + })(jQuery);