LightstreamerStore.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. define("dojox/store/LightstreamerStore", [
  2. "dojo/_base/lang",
  3. "dojo/_base/array",
  4. "dojo/_base/declare",
  5. "dojo/_base/Deferred",
  6. "dojo/store/util/QueryResults"
  7. ], function(dojo){
  8. dojo.getObject("store", true, dojox);
  9. // NOTE: The usual Lightstreamer web client MUST be loaded to use this store,
  10. // and will not be wrapped as an AMD module for now.
  11. var nextId = 0;
  12. function translate(id, updateInfo, schema, o){
  13. // private function to convert the returned object from an update to a JSON-like object.
  14. o = o || {};
  15. dojo.forEach(schema, function(field){
  16. o[field] = updateInfo.getNewValue(field);
  17. });
  18. if(!("id" in o)){ o["id"] = id; }
  19. return o;
  20. }
  21. /*=====
  22. dojox.store.LightstreamerStore.__queryOptionsArgs = function(dataAdapter, itemsRange, requestedBufferSize, requestedMaxFrequency, selector, snapshotRequired, commandLogic){
  23. // dataAdapter: String?
  24. // The data adapter to be used for a query.
  25. // itemsRange: Array?
  26. // The range of items in the form of [ start, end ] to receive back from Lightstreamer.
  27. // requestedBufferSize: Number?
  28. // The length of the internal queuing buffers to be used by the server.
  29. // requestedMaxFrequency: Number?
  30. // The maximum update frequency (updates per second) to be used by Lightstreamer.
  31. // selector: String?
  32. // The name of a selector, to be recognized by the Metadata Adapter in Lightstreamer.
  33. // snapshotRequired: Boolean?
  34. // Whether or not to request snapshot delivery.
  35. // commandLogic: Array?
  36. // An array of arguments in the following form: [ flag, commandPos, keyPos, underSchema, underDataAdapter ]
  37. this.dataAdapter = dataAdapter;
  38. this.itemsRange = itemsRange;
  39. this.requestedBufferSize = requestedBufferSize;
  40. this.requestedMaxFrequency = requestedMaxFrequency;
  41. this.selector = selector;
  42. this.snapshotRequired = snapshotRequired;
  43. this.commandLogic = commandLogic;
  44. }
  45. =====*/
  46. dojo.declare("dojox.store.LightstreamerStore", [], {
  47. _index: {}, // a cache for data objects returned
  48. // pushPage: (Lightstreamer)pushPage
  49. // The main connection created by the typical Lightstreamer Web Client
  50. pushPage: null,
  51. // group: String[]
  52. // The group of items to be returned from the Lightstreamer Server.
  53. group: [],
  54. // schema: String[]
  55. // The list of fields for each item you wish to get back from Lightstreamer
  56. schema: [],
  57. constructor: function(pushPage, group, schema, dataAdapter){
  58. // summary:
  59. // The constructor for the LightstreamerStore.
  60. // pushPage: pushPage
  61. // This is the pushPage created by using the typical Lightstreamer web client
  62. // dataAdapter: String
  63. // This is the data adapter to connect to (defined with the Lightstreamer server)
  64. // group: String[]
  65. // An array of the item names you wish to get back from Lightstreamer.
  66. // schema: String[]
  67. // The list of fields for each item you wish to get back from Lightstreamer.
  68. this.pushPage = pushPage;
  69. this.group = group;
  70. this.schema = schema;
  71. this.dataAdapter = dataAdapter || "DEFAULT";
  72. },
  73. query: function(query, options){
  74. // summary:
  75. // Start receiving streams from the Lightstreamer server.
  76. //
  77. // description:
  78. // The main method of the LightstreamerStore, query opens up a data stream
  79. // from a Lightstreamer server (based on the pushPage definition used in the
  80. // constructor) and sets up a way to observe the returned results from said
  81. // stream. It is based on Lightstreamer's NonVisualTable object, and by
  82. // default will run the return from the Lightstreamer server through a
  83. // private "translate" function, which takes the updateInfo object normally
  84. // returned by Lightstreamer's web client and converts it into a straight
  85. // JSON-like object that can be used for data consumption.
  86. //
  87. // query: String
  88. // The name of the mode to use for the resulting stream. (RAW, MERGE, COMMAND or DISTINCT)
  89. //
  90. // options: LightstreamerStore.__QueryOptionsArgs
  91. // Additional options to consume. See http://www.lightstreamer.com/docs/client_web_jsdoc/NonVisualTable.html
  92. // for more information on these properties. All properties are optional.
  93. //
  94. // returns: dojo.store.util.QueryResults
  95. // A query results object that can be used to observe data being returned,
  96. // as well as stop the stream of data. Note that this results object is
  97. // customized with an "observe" method and a "close" method; observe is the
  98. // main hook into the constant data stream returned by Lightstreamer, and
  99. // the close method will stop the query/stream.
  100. //
  101. // example:
  102. // Query a server:
  103. // | var results = myLSStore.query("MERGE", { dataAdapter: "QUOTE_ADAPTER", snapshotRequired: true });
  104. // | results.observe(function(obj){
  105. // | // do something with obj
  106. // | });
  107. options = options || {};
  108. var results = new dojo.Deferred(),
  109. snapshotReceived,
  110. resultsArray = [],
  111. self = this,
  112. id = "store-" + nextId++,
  113. pushPage = this.pushPage,
  114. table = new NonVisualTable(this.group, this.schema, query);
  115. if(!("dataAdapter" in options) && this.dataAdapter){
  116. table.setDataAdapter(this.dataAdapter);
  117. }
  118. for(var prop in options) {
  119. var setter = "set" + prop.charAt(0).toUpperCase() + prop.slice(1);
  120. if(setter in table && dojo.isFunction(table[setter])){
  121. table[setter][(dojo.isArray(options[prop])?"apply":"call")](table, options[prop]);
  122. }
  123. }
  124. table.onItemUpdate = function(id, updateInfo){
  125. var obj = translate(id, updateInfo, self.schema, self._index[id]);
  126. var newObject;
  127. if(!self._index[id]){
  128. newObject = true;
  129. self._index[id] = obj;
  130. if(!snapshotReceived){
  131. resultsArray.push(obj);
  132. }
  133. }
  134. table[snapshotReceived?"onPostSnapShot":"onPreSnapShot"](obj, newObject);
  135. };
  136. if(query == "MERGE" || options.snapshotRequired === false){
  137. snapshotReceived = true;
  138. results.resolve(resultsArray);
  139. } else { // eventually properly handle other subscription modes
  140. table.onEndOfSnapshot = function(){
  141. snapshotReceived = true;
  142. results.resolve(resultsArray);
  143. };
  144. }
  145. // note that these need to be two separate function objects.
  146. table.onPreSnapShot = function(){};
  147. table.onPostSnapShot = function(){};
  148. // modify the deferred
  149. results = dojo.store.util.QueryResults(results);
  150. // set up the two main ways of working with results
  151. var foreachHandler;
  152. results.forEach = function(callback){
  153. foreachHandler = dojo.connect(table, "onPreSnapShot", callback);
  154. };
  155. var observeHandler;
  156. results.observe = function(listener){
  157. observeHandler = dojo.connect(table, "onPostSnapShot", function(object, newObject){
  158. listener.call(results, object, newObject ? -1 : undefined);
  159. });
  160. };
  161. // set up the way to stop the stream
  162. results.close = function(){
  163. if(foreachHandler){ dojo.disconnect(foreachHandler); }
  164. if(observeHandler){ dojo.disconnect(observeHandler); }
  165. pushPage.removeTable(id);
  166. table = null;
  167. };
  168. // start up the stream
  169. pushPage.addTable(table, id);
  170. return results;
  171. },
  172. get: function(id){
  173. // summary:
  174. // Return a (cached) object from the Lightstreamer.
  175. // id: String
  176. // The identity of the object to retrieve.
  177. return this._index[id];
  178. }
  179. });
  180. return dojox.store.LightstreamerStore;
  181. });