SnapLogicStore.js 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. define("dojox/data/SnapLogicStore", ["dojo", "dojox", "dojo/io/script", "dojo/data/util/sorter"], function(dojo, dojox) {
  2. dojo.declare("dojox.data.SnapLogicStore", null, {
  3. Parts: {
  4. DATA: "data",
  5. COUNT: "count"
  6. },
  7. url: "",
  8. constructor: function(/* Object */args){
  9. // summary:
  10. // Initialize a SnapLogicStore object.
  11. // args:
  12. // An object that contains properties for initializing the new data store object. The
  13. // following properties are understood:
  14. // url:
  15. // A URL to the SnapLogic pipeline's output routed through PipeToHttp. Typically, this
  16. // will look like "http://<server-host>:<port>/pipe/<pipeline-url>/<pipeline-output-view>".
  17. // parameters:
  18. // An object whose properties define parameters to the pipeline. The values of these
  19. // properties will be sent to the pipeline as parameters when it run.
  20. //
  21. if(args.url){
  22. this.url = args.url;
  23. }
  24. this._parameters = args.parameters;
  25. },
  26. _assertIsItem: function(/* item */item){
  27. // summary:
  28. // This function tests whether the item passed in is indeed an item in the store.
  29. // item:
  30. // The item to test for being contained by the store.
  31. if(!this.isItem(item)){
  32. throw new Error("dojox.data.SnapLogicStore: a function was passed an item argument that was not an item");
  33. }
  34. },
  35. _assertIsAttribute: function(/* attribute-name-string */ attribute){
  36. // summary:
  37. // This function tests whether the item passed in is indeed a valid 'attribute' like type for the store.
  38. // attribute:
  39. // The attribute to test for being contained by the store.
  40. if(typeof attribute !== "string"){
  41. throw new Error("dojox.data.SnapLogicStore: a function was passed an attribute argument that was not an attribute name string");
  42. }
  43. },
  44. getFeatures: function(){
  45. // summary:
  46. // See dojo.data.api.Read.getFeatures()
  47. return {
  48. 'dojo.data.api.Read': true
  49. };
  50. },
  51. getValue: function(item, attribute, defaultValue){
  52. // summary:
  53. // See dojo.data.api.Read.getValue()
  54. this._assertIsItem(item);
  55. this._assertIsAttribute(attribute);
  56. var i = dojo.indexOf(item.attributes, attribute);
  57. if(i !== -1){
  58. return item.values[i];
  59. }
  60. return defaultValue;
  61. },
  62. getAttributes: function(item){
  63. // summary:
  64. // See dojo.data.api.Read.getAttributes()
  65. this._assertIsItem(item);
  66. return item.attributes;
  67. },
  68. hasAttribute: function(item, attribute){
  69. // summary:
  70. // See dojo.data.api.Read.hasAttributes()
  71. this._assertIsItem(item);
  72. this._assertIsAttribute(attribute);
  73. for(var i = 0; i < item.attributes.length; ++i){
  74. if(attribute == item.attributes[i]){
  75. return true;
  76. }
  77. }
  78. return false;
  79. },
  80. isItemLoaded: function(item){
  81. // summary:
  82. // See dojo.data.api.Read.isItemLoaded()
  83. return this.isItem(item); // Boolean
  84. },
  85. loadItem: function(keywordArgs){
  86. // summary:
  87. // See dojo.data.api.Read.loadItem()
  88. },
  89. getLabel: function(item){
  90. // summary:
  91. // See dojo.data.api.Read.getLabel()
  92. return undefined;
  93. },
  94. getLabelAttributes: function(item){
  95. // summary:
  96. // See dojo.data.api.Read.getLabelAttributes()
  97. return null;
  98. },
  99. containsValue: function(item, attribute, value){
  100. // summary:
  101. // See dojo.data.api.Read.containsValue()
  102. return this.getValue(item, attribute) === value; // Boolean
  103. },
  104. getValues: function(item, attribute){
  105. // summary:
  106. // See dojo.data.api.Read.getValue()
  107. this._assertIsItem(item);
  108. this._assertIsAttribute(attribute);
  109. var i = dojo.indexOf(item.attributes, attribute);
  110. if(i !== -1){
  111. return [item.values[i]]; // Array
  112. }
  113. return [];
  114. },
  115. isItem: function(item){
  116. // summary:
  117. // See dojo.data.api.Read.isItem()
  118. if(item && item._store === this){
  119. return true;
  120. }
  121. return false;
  122. },
  123. close: function(request){
  124. // summary:
  125. // See dojo.data.api.Read.close()
  126. },
  127. _fetchHandler: function(/* Object */request){
  128. // summary:
  129. // Process data retrieved via fetch and send it back to requester.
  130. // response:
  131. // The data returend from the I/O transport. In the normal case, it will be an array of result rows
  132. // from the pipeline. In the special case for record count optimization, response will be an array
  133. // with a single element containing the total pipeline result row count. See fetch() for details
  134. // on this optimization.
  135. var scope = request.scope || dojo.global;
  136. if(request.onBegin){
  137. // Check for the record count optimization
  138. request.onBegin.call(scope, request._countResponse[0], request);
  139. }
  140. if(request.onItem || request.onComplete){
  141. var response = request._dataResponse;
  142. if(!response.length){
  143. request.onError.call(scope,
  144. new Error("dojox.data.SnapLogicStore: invalid response of length 0"),
  145. request);
  146. return;
  147. }else if(request.query != 'record count'){
  148. //If this was not a record count request, the first element returned will contain
  149. //the field names.
  150. var field_names = response.shift();
  151. var items = [];
  152. for(var i = 0; i < response.length; ++i){
  153. if(request._aborted){
  154. break;
  155. }
  156. items.push({attributes: field_names, values: response[i], _store: this});
  157. }
  158. if(request.sort && !request._aborted){
  159. items.sort(dojo.data.util.sorter.createSortFunction(request.sort, self));
  160. }
  161. }else{
  162. //This is a record count request, so manually set the field names.
  163. items = [({attributes: ['count'], values: response, _store: this})];
  164. }
  165. if(request.onItem){
  166. for(var i = 0; i < items.length; ++i){
  167. if(request._aborted){
  168. break;
  169. }
  170. request.onItem.call(scope, items[i], request);
  171. }
  172. items = null;
  173. }
  174. if(request.onComplete && !request._aborted){
  175. request.onComplete.call(scope, items, request);
  176. }
  177. }
  178. },
  179. _partHandler: function(/* Object */request, /* String */part, /* Object */response){
  180. // summary:
  181. // Handle the individual replies for both data and length requests.
  182. // request:
  183. // The request/handle object used with the original fetch() call.
  184. // part:
  185. // A value indicating which request this handler call is for (this.Parts).
  186. // response:
  187. // Response received from the underlying IO transport.
  188. if(response instanceof Error){
  189. if(part == this.Parts.DATA){
  190. request._dataHandle = null;
  191. }else{
  192. request._countHandle = null;
  193. }
  194. request._aborted = true;
  195. if(request.onError){
  196. request.onError.call(request.scope, response, request);
  197. }
  198. }else{
  199. if(request._aborted){
  200. return;
  201. }
  202. if(part == this.Parts.DATA){
  203. request._dataResponse = response;
  204. }else{
  205. request._countResponse = response;
  206. }
  207. if((!request._dataHandle || request._dataResponse !== null) &&
  208. (!request._countHandle || request._countResponse !== null)){
  209. this._fetchHandler(request);
  210. }
  211. }
  212. },
  213. fetch: function(/* Object */request){
  214. // summary:
  215. // See dojo.data.api.Read.close()
  216. // request:
  217. // See dojo.data.api.Read.close() for generic interface.
  218. //
  219. // In addition to the standard Read API fetch support, this store supports an optimization for
  220. // for retrieving the total count of records in the Pipeline without retrieving the data. To
  221. // use this optimization, simply provide an onBegin handler without an onItem or onComplete handler.
  222. request._countResponse = null;
  223. request._dataResponse = null;
  224. request._aborted = false;
  225. request.abort = function(){
  226. if(!request._aborted){
  227. request._aborted = true;
  228. if(request._dataHandle && request._dataHandle.cancel){
  229. request._dataHandle.cancel();
  230. }
  231. if(request._countHandle && request._countHandle.cancel){
  232. request._countHandle.cancel();
  233. }
  234. }
  235. };
  236. // Only make the call for data if onItem or onComplete is used. Otherwise, onBegin will only
  237. // require the total row count.
  238. if(request.onItem || request.onComplete){
  239. var content = this._parameters || {};
  240. if(request.start){
  241. if(request.start < 0){
  242. throw new Error("dojox.data.SnapLogicStore: request start value must be 0 or greater");
  243. }
  244. content['sn.start'] = request.start + 1;
  245. }
  246. if(request.count){
  247. if(request.count < 0){
  248. throw new Error("dojox.data.SnapLogicStore: request count value 0 or greater");
  249. }
  250. content['sn.limit'] = request.count;
  251. }
  252. content['sn.content_type'] = 'application/javascript';
  253. var store = this;
  254. var handler = function(response, ioArgs){
  255. if(response instanceof Error){
  256. store._fetchHandler(response, request);
  257. }
  258. };
  259. var getArgs = {
  260. url: this.url,
  261. content: content,
  262. // preventCache: true,
  263. timeout: 60000, //Starting a pipeline can take a long time.
  264. callbackParamName: "sn.stream_header",
  265. handle: dojo.hitch(this, "_partHandler", request, this.Parts.DATA)
  266. };
  267. request._dataHandle = dojo.io.script.get(getArgs);
  268. }
  269. if(request.onBegin){
  270. var content = {};
  271. content['sn.count'] = 'records';
  272. content['sn.content_type'] = 'application/javascript';
  273. var getArgs = {
  274. url: this.url,
  275. content: content,
  276. timeout: 60000,
  277. callbackParamName: "sn.stream_header",
  278. handle: dojo.hitch(this, "_partHandler", request, this.Parts.COUNT)
  279. };
  280. request._countHandle = dojo.io.script.get(getArgs);
  281. }
  282. return request; // Object
  283. }
  284. });
  285. return dojox.data.SnapLogicStore;
  286. });