ESPResult.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. /*##############################################################################
  2. # HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. ############################################################################## */
  16. define([
  17. "dojo/_base/declare",
  18. "dojo/_base/array",
  19. "dojo/_base/Deferred",
  20. "dojo/_base/lang",
  21. "dojo/NodeList-manipulate",
  22. "dojo/data/ObjectStore",
  23. "dojo/store/util/QueryResults",
  24. "dojo/store/Observable",
  25. "dojo/dom-construct",
  26. "dojox/xml/parser",
  27. "dojox/xml/DomParser",
  28. "dojox/html/entities",
  29. "hpcc/ESPBase",
  30. "hpcc/ESPRequest",
  31. "hpcc/WsWorkunits"
  32. ], function (declare, arrayUtil, Deferred, lang, NodeListManipulate, ObjectStore, QueryResults, Observable, domConstruct,
  33. parser, DomParser, entities,
  34. ESPBase, ESPRequest, WsWorkunits) {
  35. var Store = declare([ESPRequest.Store, ESPBase], {
  36. service: "WsWorkunits",
  37. action: "WUResult",
  38. responseQualifier: "WUResultResponse.Result",
  39. responseTotalQualifier: "WUResultResponse.Total",
  40. idProperty: "__hpcc_id",
  41. startProperty: "Start",
  42. countProperty: "Count",
  43. useSingletons: false,
  44. preRequest: function (request) {
  45. if (this.name && this.cluster) {
  46. this.idPrefix = this.name + "_" + this.cluster;
  47. request['LogicalName'] = this.name;
  48. request['Cluster'] = this.cluster;
  49. } else if (this.name) {
  50. this.idPrefix = this.name;
  51. request['LogicalName'] = this.name;
  52. } else {
  53. this.idPrefix = this.wuid + "_" + this.sequence;
  54. request['Wuid'] = this.wuid;
  55. request['Sequence'] = this.sequence;
  56. }
  57. if (request.includeXmlSchema) {
  58. request['SuppressXmlSchema'] = false;
  59. } else {
  60. request['SuppressXmlSchema'] = true;
  61. }
  62. },
  63. preProcessResponse: function (response, request) {
  64. var xml = "<Result>" + response.Result + "</Result>";
  65. var domXml = parser.parse(xml);
  66. if (request.includeXmlSchema) {
  67. this.XmlSchema = this.getValues(domXml, "XmlSchema");
  68. } else {
  69. this.XmlSchema = [];
  70. }
  71. var rows = this.getValues(domXml, "Row", ["Row"]);
  72. var context = this;
  73. arrayUtil.forEach(rows, function(item, index) {
  74. item.__hpcc_rowNum = request.Start + index + 1;
  75. item.__hpcc_id = context.idPrefix + "_" + item.__hpcc_rowNum;
  76. });
  77. response.Result = rows;
  78. }
  79. });
  80. var Result = declare(null, {
  81. store: null,
  82. Total: "-1",
  83. constructor: function (args) {
  84. if (args) {
  85. declare.safeMixin(this, args);
  86. }
  87. if (lang.exists("Sequence", this)) {
  88. this.store = new Store({
  89. wuid: this.Wuid,
  90. sequence: this.Sequence,
  91. isComplete: this.isComplete()
  92. });
  93. } else if (lang.exists("Name", this) && lang.exists("ClusterName", this)) {
  94. this.store = new Store({
  95. wuid: this.Wuid,
  96. cluster: this.ClusterName,
  97. name: this.Name,
  98. isComplete: true
  99. });
  100. } else {
  101. this.store = new Store({
  102. wuid: this.Wuid,
  103. cluster: this.Cluster,
  104. name: this.Name,
  105. isComplete: true
  106. });
  107. }
  108. },
  109. getName: function () {
  110. return this.Name;
  111. },
  112. getID: function () {
  113. if (this.Sequence != null) {
  114. return this.Sequence;
  115. }
  116. return this.Name;
  117. },
  118. isComplete: function () {
  119. return this.Total != "-1";
  120. },
  121. canShowResults: function () {
  122. if (lang.exists("Sequence", this)) { // Regular WU result
  123. return true;
  124. } else if (lang.exists("RecordCount", this) && this.RecordCount != "") { // DFU Sprayed CSV File will fail here
  125. return true;
  126. }
  127. return false;
  128. },
  129. getFirstSchemaNode: function (node, name) {
  130. if (node && node.attributes) {
  131. if ((node.baseName && node.baseName == name) || (node.localName && node.localName == name) || (typeof (node.getAttribute) != "undefined" && node.getAttribute("name") == name)) {
  132. return node;
  133. }
  134. }
  135. for (var i = 0; i < node.childNodes.length; ++i) {
  136. var retVal = this.getFirstSchemaNode(node.childNodes[i], name);
  137. if (retVal) {
  138. return retVal;
  139. }
  140. }
  141. return null;
  142. },
  143. getFirstSequenceNode: function (schemaNode) {
  144. var row = this.getFirstSchemaNode(schemaNode, "Row");
  145. if (!row)
  146. row = schemaNode;
  147. var complexType = this.getFirstSchemaNode(row, "complexType");
  148. if (!complexType)
  149. return null;
  150. return this.getFirstSchemaNode(complexType, "sequence");
  151. },
  152. rowToTable: function (cell, __row, node) {
  153. var table = domConstruct.create("table", { border: 1, cellspacing: 0, width: "100%" }, node);
  154. if (Object.prototype.toString.call(cell) === '[object Object]') {
  155. cell = [cell];
  156. }
  157. if (Object.prototype.toString.call(cell) === '[object Array]') {
  158. for (var i = 0; i < cell.length; ++i) {
  159. if (i == 0) {
  160. var tr = domConstruct.create("tr", null, table);
  161. for (var key in cell[i]) {
  162. var th = domConstruct.create("th", { innerHTML: entities.encode(key) }, tr);
  163. }
  164. }
  165. var tr = domConstruct.create("tr", null, table);
  166. for (var key in cell[i]) {
  167. if (cell[i][key]) {
  168. if (Object.prototype.toString.call(cell[i][key]) === '[object Object]' || Object.prototype.toString.call(cell[i][key]) === '[object Array]') {
  169. var td = domConstruct.create("td", null, tr);
  170. this.rowToTable(cell[i][key], cell[i], td);
  171. } else if (key.indexOf("__html", key.length - "__html".length) !== -1) {
  172. var td = domConstruct.create("td", { innerHTML : cell[i][key] }, tr);
  173. } else if (key.indexOf("__javascript", key.length - "__javascript".length) !== -1) {
  174. var td = domConstruct.create("td", null, tr);
  175. this.injectJavascript(cell[i][key], cell[i], td);
  176. } else {
  177. var td = domConstruct.create("td", { innerHTML: entities.encode(cell[i][key]) }, tr);
  178. }
  179. } else {
  180. var td = domConstruct.create("td", { innerHTML: "" }, tr);
  181. }
  182. }
  183. }
  184. }
  185. },
  186. injectJavascript : function(__cellContent, __row, __cell, __width) {
  187. // Add paragraph so cells can valign ---
  188. domConstruct.create("p", {
  189. style: {
  190. height : "1px"
  191. },
  192. innerHTML: "&nbsp;"
  193. }, __cell);
  194. try {
  195. eval(__cellContent);
  196. } catch (e) {
  197. __cell.innerHTML = "<b>Error:</b>&nbsp;&nbsp;" + entities.encode(e.message) + "<br>" + entities.encode(__cellContent);
  198. }
  199. },
  200. parseName: function (nameObj) {
  201. nameObj.width = 500;
  202. var titleParts = nameObj.name.split("__");
  203. if (titleParts.length >= 3) {
  204. var specifiedWidth = parseInt(titleParts[titleParts.length - 2]);
  205. if (!isNaN(specifiedWidth)) {
  206. nameObj.width = specifiedWidth;
  207. titleParts = titleParts.slice(0, titleParts.length - 1);
  208. }
  209. }
  210. titleParts = titleParts.slice(0, titleParts.length - 1);
  211. nameObj.displayName = titleParts.join("__");
  212. },
  213. getRowStructureFromSchema: function (parentNode, prefix) {
  214. var sequence = this.getFirstSequenceNode(parentNode, "sequence");
  215. if (!sequence)
  216. return null;
  217. var retVal = [];
  218. for (var i = 0; i < sequence.childNodes.length; ++i) {
  219. var node = sequence.childNodes[i];
  220. if (typeof (node.getAttribute) != "undefined") {
  221. var name = node.getAttribute("name");
  222. var type = node.getAttribute("type");
  223. var children = this.getRowStructureFromSchema(node, name + "_");
  224. var context = this;
  225. if (name && name.indexOf("__hidden", name.length - "__hidden".length) !== -1) {
  226. } else if (name && type) {
  227. if (name.indexOf("__html", name.length - "__html".length) !== -1) {
  228. var nameObj = {
  229. name: name
  230. };
  231. this.parseName(nameObj);
  232. retVal.push({
  233. label: nameObj.displayName,
  234. field: prefix + name,
  235. width: nameObj.width,
  236. className: "resultGridCell",
  237. formatter: function (cell, row) {
  238. return cell;
  239. },
  240. sortable: false
  241. });
  242. } else if (name.indexOf("__javascript", name.length - "__javascript".length) !== -1) {
  243. var nameObj = {
  244. name: name
  245. };
  246. this.parseName(nameObj);
  247. retVal.push({
  248. label: nameObj.displayName,
  249. field: prefix + name,
  250. width: nameObj.width,
  251. className: "resultGridCell",
  252. renderCell: function(row, cell, node, options) {
  253. context.injectJavascript(cell, row, node, this.width)
  254. },
  255. sortable: false
  256. });
  257. } else {
  258. retVal.push({
  259. label: name,
  260. field: prefix + name,
  261. width: this.extractWidth(type, name) * 9,
  262. className: "resultGridCell",
  263. sortable: false
  264. });
  265. }
  266. } else if (children) {
  267. var childWidth = 10; // Allow for html table
  268. arrayUtil.forEach(children, function(item, idx) {
  269. childWidth += item.width;
  270. });
  271. /*
  272. retVal.push({
  273. label: name,
  274. children: children,
  275. width: childWidth,
  276. className: "resultGridCell",
  277. sortable: false
  278. });
  279. */
  280. retVal.push({
  281. label: name,
  282. field: name,
  283. renderCell: function(row, cell, node, options) {
  284. context.rowToTable(cell, row, node);
  285. },
  286. width: childWidth,
  287. className: "resultGridCell",
  288. sortable: false
  289. });
  290. }
  291. }
  292. }
  293. return retVal.length ? retVal : null;
  294. },
  295. getRowStructureFromData: function (rows) {
  296. var retVal = [];
  297. for (var key in rows[0]) {
  298. if (key != "myInjectedRowNum") {
  299. var context = this;
  300. retVal.push({
  301. label: key,
  302. field: key,
  303. formatter: function (cell, row, grid) {
  304. if (Object.prototype.toString.call(cell) === '[object Object]' || Object.prototype.toString.call(cell) === '[object Array]') {
  305. var div = document.createElement("div");
  306. context.rowToTable(cell, row, div);
  307. return div.innerHTML;
  308. }
  309. return cell;
  310. },
  311. width: context.extractWidth("string12", key) * 9,
  312. className: "resultGridCell"
  313. });
  314. }
  315. }
  316. return retVal;
  317. },
  318. getStructure: function () {
  319. var structure = [
  320. {
  321. cells: [
  322. [
  323. {
  324. label: "##", field: "__hpcc_rowNum", width: 54, className: "resultGridCell", sortable: false
  325. }
  326. ]
  327. ]
  328. }
  329. ];
  330. var dom = parser.parse(this.XmlSchema);
  331. var dataset = this.getFirstSchemaNode(dom, "Dataset");
  332. var innerStruct = this.getRowStructureFromSchema(dataset, "");
  333. for (var i = 0; i < innerStruct.length; ++i) {
  334. structure[0].cells[structure[0].cells.length - 1].push(innerStruct[i]);
  335. }
  336. return structure[0].cells[0];
  337. },
  338. fetchStructure: function (callback) {
  339. if (this.XmlSchema) {
  340. callback(this.getStructure());
  341. } else {
  342. var context = this;
  343. var request = {};
  344. if (this.Wuid && lang.exists("Sequence", this)) {
  345. request['Wuid'] = this.Wuid;
  346. request['Sequence'] = this.Sequence;
  347. } else if (this.Name && this.ClusterName) {
  348. request['LogicalName'] = this.Name;
  349. request['Cluster'] = this.ClusterName;
  350. } else if (this.Name) {
  351. request['LogicalName'] = this.Name;
  352. }
  353. request['Start'] = 0;
  354. request['Count'] = 1;
  355. WsWorkunits.WUResult({
  356. request: request,
  357. load: function (response) {
  358. if (lang.exists("WUResultResponse.Result", response)) {
  359. context.XmlSchema = "<Result>" + response.WUResultResponse.Result + "</Result>";
  360. callback(context.getStructure());
  361. }
  362. /*
  363. if (rows.length) {
  364. var innerStruct = context.getRowStructureFromData(rows);
  365. for (var i = 0; i < innerStruct.length; ++i) {
  366. structure[0].cells[structure[0].cells.length - 1].push(innerStruct[i]);
  367. }
  368. }
  369. */
  370. }
  371. });
  372. }
  373. },
  374. getRowWidth: function (parentNode) {
  375. var retVal = 0;
  376. var sequence = this.getFirstSequenceNode(parentNode, "sequence");
  377. if (!sequence)
  378. return retVal;
  379. for (var i = 0; i < sequence.childNodes.length; ++i) {
  380. var node = sequence.childNodes[i];
  381. if (typeof (node.getAttribute) != "undefined") {
  382. var name = node.getAttribute("name");
  383. var type = node.getAttribute("type");
  384. if (name && type) {
  385. retVal += this.extractWidth(type, name);
  386. } else if (node.hasChildNodes()) {
  387. retVal += this.getRowWidth(node);
  388. }
  389. }
  390. }
  391. return retVal;
  392. },
  393. extractWidth: function (type, name) {
  394. var retVal = -1;
  395. switch (type) {
  396. case "xs:boolean":
  397. retVal = 5;
  398. break;
  399. case "xs:integer":
  400. retVal = 8;
  401. break;
  402. case "xs:nonNegativeInteger":
  403. retVal = 8;
  404. break;
  405. case "xs:double":
  406. retVal = 8;
  407. break;
  408. case "xs:string":
  409. retVal = 32;
  410. break;
  411. default:
  412. var numStr = "0123456789";
  413. var underbarPos = type.lastIndexOf("_");
  414. var length = underbarPos > 0 ? underbarPos : type.length;
  415. var i = length - 1;
  416. for (; i >= 0; --i) {
  417. if (numStr.indexOf(type.charAt(i)) == -1)
  418. break;
  419. }
  420. if (i + 1 < length) {
  421. retVal = parseInt(type.substring(i + 1, length));
  422. }
  423. if (type.indexOf("data") == 0) {
  424. retVal *= 2;
  425. }
  426. break;
  427. }
  428. if (retVal < name.length)
  429. retVal = name.length;
  430. return retVal;
  431. },
  432. getStore: function () {
  433. return this.store;
  434. },
  435. fetchContent: function () {
  436. var deferred = new Deferred()
  437. var context = this;
  438. this.store.query({
  439. Start: 0,
  440. Count: 1
  441. }).total.then(function(total) {
  442. context.store.query({
  443. Start: 0,
  444. Count: total
  445. }).then(function(results) {
  446. deferred.resolve(results);
  447. });
  448. });
  449. return deferred.promise;
  450. },
  451. getObjectStore: function () {
  452. return new ObjectStore({
  453. objectStore: this.store
  454. });
  455. },
  456. getLoadingMessage: function () {
  457. if (lang.exists("wu.state", this)) {
  458. return "<span class=\'dojoxGridWating\'>[" + this.wu.state + "]</span>";
  459. }
  460. return "<span class=\'dojoxGridWating\'>[unknown]</span>";
  461. },
  462. getECLRecord: function () {
  463. var retVal = "RECORD\n";
  464. for (var i = 0; i < this.ECLSchemas.ECLSchemaItem.length; ++i) {
  465. retVal += "\t" + this.ECLSchemas.ECLSchemaItem[i].ColumnType + "\t" + this.ECLSchemas.ECLSchemaItem[i].ColumnName + ";\n";
  466. }
  467. retVal += "END;\n";
  468. return retVal;
  469. }
  470. });
  471. return {
  472. CreateWUResultObjectStore: function (options) {
  473. var store = new Store(options);
  474. store = Observable(store);
  475. var objStore = new ObjectStore({ objectStore: store });
  476. return objStore;
  477. },
  478. Get: function (params) {
  479. return new Result(params);
  480. }
  481. }
  482. });