src/js/libs/tracemanager.js
branchpopcorn-port
changeset 835 a8af9da7c622
child 841 8da49ff273e0
equal deleted inserted replaced
834:573c7ca752e0 835:a8af9da7c622
       
     1 /*
       
     2  * Modelled Trace API
       
     3  */
       
     4 IriSP.TraceManager = function($) {
       
     5      /*
       
     6       * FIXME: Write proper representation functions (str, json, ...)
       
     7       */
       
     8 
       
     9      var BufferedService_prototype = {
       
    10          /*
       
    11           *  Buffered service for traces
       
    12           */
       
    13          // url: "",
       
    14          // buffer: [],
       
    15          // isReady: false,
       
    16          // timer: null,
       
    17 
       
    18          /* Flush buffer */
       
    19          flush: function() {
       
    20              // FIXME: should add a counter to avoid starving the sync
       
    21              // process in case of too many generated obsels.
       
    22              // FIXME: add mutex on this.buffer
       
    23              if (! this.isReady)
       
    24              {
       
    25                  console.log("Sync service not ready");
       
    26              } else if (this.buffer.length) {
       
    27                  var temp = this.buffer;
       
    28                  this.buffer = [];
       
    29 
       
    30                  if (this.mode == 'GET')
       
    31                  {
       
    32                      // GET mode: do some data mangline. We mark the
       
    33                      // "compressed" nature of the generated JSON by
       
    34                      // prefixing it with c
       
    35                      var data = 'c' + JSON.stringify(temp.map(function (o) { return o.toCompactJSON(); }));
       
    36                      // Swap " (very frequent, which will be
       
    37                      // serialized into %22) and / (rather rare), this
       
    38                      // saves some bytes
       
    39                      data = data.replace(/[\/"]/g, function(s){ return s == '/' ? '"' : '/'; }).replace('#','%23');
       
    40                      // FIXME: check data length (< 2K is safe)
       
    41                      var request=$('<img/>').attr('src', this.url + 'trace/?data=' + data);
       
    42                  }
       
    43                  else
       
    44                  {
       
    45                      $.ajax({ url: this.url + 'trace/',
       
    46                               type: 'POST',
       
    47                               contentType: 'application/json',
       
    48                               data: JSON.stringify(temp.map(function (o) { return o.toJSON(); })),
       
    49                               processData: false,
       
    50                               // Type of the returned data.
       
    51                               dataType: "html",
       
    52                               error: function(jqXHR, textStatus, errorThrown) {
       
    53                                   // FIXME: not called for JSONP/crossdomain
       
    54                                   console.log("Error when sending buffer:", textStatus);
       
    55                               },
       
    56                               success: function(data, textStatus, jqXHR) {
       
    57                                   // FIXME: parse the returned JSON, and get
       
    58                                   // the updated properties (id, uri...) to apply them to temp items
       
    59                               }
       
    60                             });
       
    61                  }
       
    62              }
       
    63          },
       
    64 
       
    65          /* Enqueue an obsel */
       
    66          enqueue: function(obsel) {
       
    67              this.buffer.push(obsel);
       
    68          },
       
    69 
       
    70          start_timer: function() {
       
    71              var self = this;
       
    72              if (this.timer === null) {
       
    73                  this.timer = window.setInterval(function() {
       
    74                                                      console.log("Flushing timeout");
       
    75                                                      self.flush();
       
    76                                                  }, this.timeOut);
       
    77              }
       
    78          },
       
    79 
       
    80          stop_timer: function() {
       
    81              if (this.timer !== null) {
       
    82                  window.clearInterval(this.timer);
       
    83                  this.timer = null;
       
    84              }
       
    85          },
       
    86 
       
    87          /*
       
    88           * Initialize the sync service
       
    89           */
       
    90          init: function() {
       
    91              var self = this;
       
    92              if (this.isReady)
       
    93                  /* Already initialized */
       
    94                  return;
       
    95              if (this.mode == 'GET')
       
    96              {
       
    97                  var request=$('<img/>').attr('src', this.url + 'login?userinfo={"name":"ktbs4js"}');
       
    98                  // Do not wait for the return, assume it is
       
    99                  // initialized. This assumption will not work anymore
       
   100                  // if login returns some necessary information
       
   101                  this.isReady = true;
       
   102              }
       
   103              else
       
   104              {
       
   105                  $.ajax({ url: this.url + 'login',
       
   106                           type: 'POST',
       
   107                           data: 'userinfo={"name":"ktbs4js"}',
       
   108                           success: function(data, textStatus, jqXHR) {
       
   109                               self.isReady = true;
       
   110                               if (self.buffer.length) {
       
   111                                   self.flush();
       
   112                               }
       
   113                           }
       
   114                         });
       
   115              }
       
   116          }
       
   117      };
       
   118      var BufferedService = function(url, mode) {
       
   119          this.url = url;
       
   120          this.buffer = [];
       
   121          this.isReady = false;
       
   122          this.timer = null;
       
   123          /* mode can be either POST or GET */
       
   124          if (mode == 'POST' || mode == 'GET')
       
   125              this.mode = mode;
       
   126          else
       
   127              this.mode = 'POST';
       
   128          /* Flush buffer every timeOut ms if the sync_mode is delayed */
       
   129          this.timeOut = 2000;
       
   130      };
       
   131      BufferedService.prototype = BufferedService_prototype;
       
   132 
       
   133      var Trace_prototype = {
       
   134          /* FIXME: We could/should use a sorted list such as
       
   135           http://closure-library.googlecode.com/svn/docs/class_goog_structs_AvlTree.html
       
   136           to speed up queries based on time */
       
   137          obsels: [],
       
   138          /* Trace URI */
       
   139          uri: "",
       
   140          sync_mode: "none",
       
   141          default_subject: "",
       
   142          /* baseuri is used as the base URI to resolve relative
       
   143           * attribute-type names in obsels. Strictly speaking, this
       
   144           * should rather be expressed as a reference to model, or
       
   145           * more generically, as a qname/URI dict */
       
   146          baseuri: "",
       
   147          /* Mapping of obsel type or property name to a compact
       
   148           * representation (shorthands).
       
   149           */
       
   150          shorthands: null,
       
   151          syncservice: null,
       
   152 
       
   153          /* Define the trace URI */
       
   154          set_uri: function(uri) {
       
   155              this.uri = uri;
       
   156          },
       
   157 
       
   158          /* Sync mode: delayed, sync (immediate sync), none (no
       
   159           * synchronisation with server, the trace has to be explicitly saved
       
   160           * if needed */
       
   161          set_sync_mode: function(mode) {
       
   162              this.sync_mode = mode;
       
   163              if (this.syncservice != null) {
       
   164                  if (mode !== 'none') {
       
   165                      this.syncservice.init();
       
   166                  }
       
   167                  if (mode == 'delayed') {
       
   168                      this.syncservice.start_timer();
       
   169                  } else {
       
   170                      this.syncservice.stop_timer();
       
   171                  }
       
   172              }
       
   173          },
       
   174 
       
   175          /*
       
   176           * Return a list of the obsels of this trace matching the parameters
       
   177           */
       
   178          list_obsels: function(_begin, _end, _reverse) {
       
   179              var res;
       
   180              if (typeof _begin !== 'undefined' || typeof _end !== 'undefined') {
       
   181                  /*
       
   182                   * Not optimized yet.
       
   183                   */
       
   184                  res = [];
       
   185                  var l = this.obsels.length;
       
   186                  for (var i = 0; i < l; i++) {
       
   187                      var o = this.obsels[i];
       
   188                      if ((typeof _begin !== 'undefined' && o.begin > _begin) && (typeof _end !== 'undefined' && o.end < _end)) {
       
   189                          res.push(o);
       
   190                      }
       
   191                  }
       
   192              }
       
   193 
       
   194              if (typeof _reverse !== 'undefined') {
       
   195                  if (res !== undefined) {
       
   196                      /* Should reverse the whole list. Make a copy. */
       
   197                      res = this.obsels.slice(0);
       
   198                  }
       
   199                  res.sort(function(a, b) { return b.begin - a.begin; });
       
   200                  return res;
       
   201              }
       
   202 
       
   203              if (res === undefined) {
       
   204                  res = this.obsels;
       
   205              }
       
   206              return res;
       
   207 
       
   208          },
       
   209 
       
   210          /*
       
   211           * Return the obsel of this trace identified by the URI, or undefined
       
   212           */
       
   213          get_obsel: function(id) {
       
   214              for (var i = 0; i < this.obsels.length; i++) {
       
   215                  /* FIXME: should check against variations of id/uri, take this.baseuri into account */
       
   216                  if (this.obsels[i].uri === id) {
       
   217                      return this.obsels[i];
       
   218                  }
       
   219              }
       
   220              return undefined;
       
   221          },
       
   222 
       
   223          set_default_subject: function(subject) {
       
   224              this.default_subject = subject;
       
   225          },
       
   226 
       
   227          get_default_subject: function() {
       
   228              return this.default_subject;
       
   229          },
       
   230 
       
   231          /* (type:ObselType, begin:int, end:int?, subject:str?, attributes:[AttributeType=>any]?) */
       
   232          /* Create a new obsel and add it to the trace */
       
   233          create_obsel: function(type, begin, end, subject, _attributes) {
       
   234              var o = new Obsel(type, begin, end, subject);
       
   235              if (typeof _attributes !== 'undefined') {
       
   236                  o.attributes = _attributes;
       
   237              }
       
   238              o.trace = this;
       
   239              this.obsels.push(o);
       
   240              if (this.syncservice !== null && this.sync_mode != 'none') {
       
   241                  this.syncservice.enqueue(o);
       
   242                  if (this.sync_mode === 'sync') {
       
   243                      // Immediate sync of the obsel.
       
   244                      this.syncservice.flush();
       
   245                  }
       
   246              }
       
   247          },
       
   248 
       
   249 	     obselProbe : function(element, bindingEvent, ObselFunction) {
       
   250 			console.log("!!!!!!!!- ICI -!!!!!!!!!");
       
   251 			console.log(element);
       
   252 			console.log(bindingEvent);
       
   253 			console.log(ObselFunction);
       
   254 
       
   255 	        //var myOPI = self.setInterval("ObselProbeInterval("+element+","+bindingEvent+","+ObselFunction+")",1000);
       
   256 			var myOPI = self.setInterval("ObselProbeInterval("+element+")",1000);
       
   257 			//var ObselProbeInterval = function(element, bindingEvent, ObselFunction){
       
   258 			var ObselProbeInterval = function(element) {
       
   259 				console.log("!!!!!!!!- ObselProbeInterval -!!!!!!!!!");
       
   260 				console.log($(element).length);
       
   261 				/*
       
   262 				if($(element).length!=0){
       
   263 					$(element).bind(bindingEvent, ObselFunction );
       
   264 					this.clearInterval();
       
   265 				}else{	console.log("!!!!!!!!- EXISTE PAS -!!!!!!!!!")
       
   266 				}
       
   267 				*/
       
   268 				//
       
   269 			};
       
   270 
       
   271 		 },
       
   272          /* Helper methods */
       
   273 
       
   274          /* Create a new obsel with the given attributes */
       
   275          trace: function(type, _attributes, _begin, _end, _subject) {
       
   276              var t = (new Date()).getTime();
       
   277              if (typeof begin === 'undefined') {
       
   278                  _begin = t;
       
   279              }
       
   280              if (typeof end === 'undefined') {
       
   281                  _end = _begin;
       
   282              }
       
   283              if (typeof subject === 'undefined') {
       
   284                  _subject = this.default_subject;
       
   285              }
       
   286              if (typeof _attributes === 'undefined') {
       
   287                  _attributes = {};
       
   288              }
       
   289              return this.create_obsel(type, _begin, _end, _subject, _attributes);
       
   290          }
       
   291      };
       
   292 
       
   293      var Trace = function(uri, requestmode) {
       
   294          /* FIXME: We could/should use a sorted list such as
       
   295           http://closure-library.googlecode.com/svn/docs/class_goog_structs_AvlTree.html
       
   296           to speed up queries based on time */
       
   297          this.obsels = [];
       
   298          /* Trace URI */
       
   299          if (uri === undefined)
       
   300              uri = "";
       
   301          this.uri = uri;
       
   302          this.sync_mode = "none";
       
   303          this.default_subject = "";
       
   304          this.shorthands = {};
       
   305          /* baseuri is used a the base URI to resolve relative attribute names in obsels */
       
   306          this.baseuri = "";
       
   307 
       
   308          this.syncservice = new BufferedService(uri, requestmode);
       
   309          $(window).unload( function () {
       
   310                                if (this.syncservice && this.sync_mode !== 'none') {
       
   311                                    this.syncservice.flush();
       
   312                                    this.syncservice.stop_timer();
       
   313                                }
       
   314                            });
       
   315      };
       
   316      Trace.prototype = Trace_prototype;
       
   317 
       
   318      var Obsel_prototype = {
       
   319          /* The following attributes are here for documentation
       
   320           * purposes. They MUST be defined in the constructor
       
   321           * function. */
       
   322          trace: undefined,
       
   323 		 obselProbe: undefined,
       
   324          type: undefined,
       
   325          begin: undefined,
       
   326          end: undefined,
       
   327          subject: undefined,
       
   328          /* Dictionary indexed by ObselType URIs */
       
   329          attributes: {},
       
   330 
       
   331          /* Method definitions */
       
   332          get_trace: function() {
       
   333              return this.trace;
       
   334          },
       
   335 
       
   336          get_obsel_type: function() {
       
   337              /* FIXME: maybe we should return a ObselType object. In the meantime, return the URI */
       
   338              return this.type;
       
   339          },
       
   340          get_begin: function() {
       
   341              return this.begin;
       
   342          },
       
   343          get_end: function() {
       
   344              return this.end;
       
   345          },
       
   346          get_subject: function() {
       
   347              return this.subject;
       
   348          },
       
   349 
       
   350          list_attribute_types: function() {
       
   351              var result = [];
       
   352              for (var prop in this.attributes) {
       
   353                  result.push(prop);
       
   354              }
       
   355              /* FIXME: we return URIs here instead of AttributeType elements */
       
   356              return result;
       
   357          },
       
   358 
       
   359          list_relation_types: function() {
       
   360              /* FIXME: not implemented yet */
       
   361          },
       
   362 
       
   363          list_related_obsels: function (rt) {
       
   364              /* FIXME: not implemented yet */
       
   365          },
       
   366          list_inverse_relation_types: function () {
       
   367              /* FIXME: not implemented yet */
       
   368          },
       
   369          list_relating_obsels: function (rt) {
       
   370              /* FIXME: not implemented yet */
       
   371          },
       
   372          /*
       
   373           * Return the value of the given attribute type for this obsel
       
   374           */
       
   375          get_attribute_value: function(at) {
       
   376              if (typeof at === "string")
       
   377                  /* It is a URI */
       
   378                  return this.attributes[at];
       
   379              else
       
   380                  /* FIXME: check that at is instance of AttributeType */
       
   381                  return this.attributes[at.uri];
       
   382          },
       
   383 
       
   384 
       
   385          /* obsel modification (trace amendment) */
       
   386 
       
   387          set_attribute_value: function(at, value) {
       
   388              if (typeof at === "string")
       
   389                  /* It is a URI */
       
   390                  this.attributes[at] = value;
       
   391              /* FIXME: check that at is instance of AttributeType */
       
   392              else
       
   393                  this.attributes[at.uri] = value;
       
   394          },
       
   395 
       
   396          del_attribute_value: function(at) {
       
   397              if (typeof at === "string")
       
   398                  /* It is a URI */
       
   399                  delete this.attributes[at];
       
   400              /* FIXME: check that at is instance of AttributeType */
       
   401              else
       
   402                  delete this.attributes[at.uri];
       
   403          },
       
   404 
       
   405          add_related_obsel: function(rt, value) {
       
   406              /* FIXME: not implemented yet */
       
   407          },
       
   408 
       
   409          del_related_obsel: function(rt, value) {
       
   410              /* FIXME: not implemented yet */
       
   411          },
       
   412 
       
   413          /*
       
   414           * Return a JSON representation of the obsel
       
   415           */
       
   416          toJSON: function() {
       
   417              var r = {
       
   418                  "@id": this.id,
       
   419                  "@type": this.type,
       
   420                  "begin": this.begin,
       
   421                  "end": this.end,
       
   422                  "subject": this.subject
       
   423              };
       
   424              for (var prop in this.attributes) {
       
   425                  r[prop] = this.attributes[prop];
       
   426              }
       
   427              return r;
       
   428          },
       
   429 
       
   430          /*
       
   431           * Return a compact JSON representation of the obsel.
       
   432           * Use predefined + custom shorthands for types/properties
       
   433           */
       
   434          toCompactJSON: function() {
       
   435              var r = {
       
   436                  "@i": this.id,
       
   437                  "@t": (this.trace.shorthands.hasOwnProperty(this.type)
       
   438                         ? this.trace.shorthands[this.type] : this.type),
       
   439                  "@b": this.begin,
       
   440                  "@e": this.end,
       
   441                  "@s": this.subject
       
   442              };
       
   443              for (var prop in this.attributes) {
       
   444                  var v = this.attributes[prop];
       
   445                  r[prop] = this.trace.shorthands.hasOwnProperty(v) ? this.trace.shorthands[v] : v;
       
   446              }
       
   447              return r;
       
   448          },
       
   449 
       
   450          toJSONstring: function() {
       
   451              return JSON.stringify(this.toJSON());
       
   452          }
       
   453      };
       
   454 
       
   455      var Obsel = function(type, begin, end, subject, attributes) {
       
   456          this.trace = undefined;
       
   457          this.uri = "";
       
   458          this.id = "";
       
   459          this.type = type;
       
   460          this.begin = begin;
       
   461          this.end = end;
       
   462          this.subject = subject;
       
   463          /* Is the obsel synched with the server ? */
       
   464          this.sync_status = false;
       
   465          /* Dictionary indexed by ObselType URIs */
       
   466          this.attributes = {};
       
   467      };
       
   468      Obsel.prototype = Obsel_prototype;
       
   469 
       
   470      var TraceManager_prototype = {
       
   471          traces: [],
       
   472          /*
       
   473           * Return the trace with id name
       
   474           * If it was not registered, return undefined.
       
   475           */
       
   476          get_trace: function(name) {
       
   477              return this.traces[name];
       
   478          },
       
   479 
       
   480          /*
       
   481           * Explicitly create and initialize a new trace with the given name.
       
   482           * The optional uri parameter allows to initialize the trace URI.
       
   483           *
       
   484           * If another existed with the same name before, then it is replaced by a new one.
       
   485           */
       
   486          init_trace: function(name, params)
       
   487          {
       
   488              console.log("init_trace", params);
       
   489              url = params.url ? params.url : "";
       
   490              requestmode = params.requestmode ? params.requestmode : "POST";
       
   491              syncmode = params.syncmode ? params.syncmode : "none";
       
   492              var t = new Trace(url, requestmode);
       
   493              t.set_sync_mode(syncmode);
       
   494              this.traces[name] = t;
       
   495              return t;
       
   496          }
       
   497      };
       
   498 
       
   499      var TraceManager = function() {
       
   500          this.traces = {};
       
   501      };
       
   502      TraceManager.prototype = TraceManager_prototype;
       
   503 
       
   504      return new TraceManager();
       
   505  };