ESPResult.js 19 KB

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