ESPResult.js 19 KB

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