ESPResult.js 20 KB

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