RAPReportInfo.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647
  1. /*
  2. *+------------------------------------------------------------------------+
  3. *| Licensed Materials - Property of IBM
  4. *| IBM Cognos Products: Viewer
  5. *| (C) Copyright IBM Corp. 2001, 2013
  6. *|
  7. *| US Government Users Restricted Rights - Use, duplication or
  8. *| disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  9. *|
  10. *+------------------------------------------------------------------------+
  11. */
  12. /**
  13. * RAPReportInfo encapsulates information returned from getInfo
  14. * A RAPReportInfo instance attached to the viewer object is automatically updated
  15. * for each response.
  16. */
  17. function RAPReportInfo(reportInfo, oCV)
  18. {
  19. this.m_reportInfoJSON = reportInfo;
  20. this.m_containerInfoJSON = {};
  21. this.m_iContainerCount = 0;
  22. this.m_bPromptPart = null;
  23. this.m_bSingleContainer = null;
  24. this.m_bDetailFilteringDisabled = null;
  25. this.m_aDrilledOnHUNs = null;
  26. this.m_bPassTrackingToBUA = null;
  27. this.m_sDisplayTypes = null;
  28. this.m_bContainsInteractiveDataContainer = null;
  29. this.m_bContainsFilters = false;
  30. this.m_bContainsSlider = false;
  31. //The referenceInfoObject is a map that supports the "isReferenced()" method.
  32. //A caller can ask reportInfo if an entity is referenced (usu. by name).
  33. this.m_referenceInfoObject = {};
  34. this.initializeContainerInfo();
  35. this._addNonVisibleReferences(this.m_reportInfoJSON.reportLevelProperties);
  36. this._populateHun( oCV );
  37. }
  38. /**
  39. * initialize the reportInfo and its containers as an associative array.
  40. */
  41. RAPReportInfo.prototype.initializeContainerInfo = function() {
  42. if(this.m_reportInfoJSON)
  43. {
  44. var reportInfoContainerArray = this.m_reportInfoJSON.containers;
  45. if (reportInfoContainerArray) {
  46. this.m_iContainerCount = reportInfoContainerArray.length;
  47. for(var containerIdx = 0; containerIdx < this.m_iContainerCount; ++containerIdx)
  48. {
  49. var containerLID=reportInfoContainerArray[containerIdx].container;
  50. this.m_containerInfoJSON[containerLID]=reportInfoContainerArray[containerIdx];
  51. this.m_containerInfoJSON[containerLID].m_itemInfoJSON = this._initializeItemInfo(reportInfoContainerArray[containerIdx].itemInfo);
  52. this.m_containerInfoJSON[containerLID].m_drillabilityJSON = this._initializeDrillability(reportInfoContainerArray[containerIdx].drillability);
  53. this._addFilterReferences(reportInfoContainerArray[containerIdx].filter);
  54. this._addSliderReferences(reportInfoContainerArray[containerIdx].sliders);
  55. // the position of the container is used for the infoBar - keep track of it for now but should be refactored if ever
  56. // we revisit the info bar
  57. this.m_containerInfoJSON[containerLID].layoutIndex = containerIdx;
  58. if(reportInfoContainerArray[containerIdx].filter) {
  59. this.m_bContainsFilters = true;
  60. }
  61. if(reportInfoContainerArray[containerIdx].sliders) {
  62. this.m_bContainsSlider = true;
  63. }
  64. }
  65. }
  66. }
  67. };
  68. RAPReportInfo.prototype._initializeItemInfo = function(itemInfo) {
  69. var itemInfoJSON = {};
  70. for( var idx in itemInfo )
  71. {
  72. itemInfoJSON[itemInfo[idx].item] = itemInfo[idx];
  73. this.m_referenceInfoObject[itemInfo[idx].item] = true;
  74. }
  75. return itemInfoJSON;
  76. };
  77. RAPReportInfo.prototype._initializeDrillability = function(drillability) {
  78. var drillabilityJSON = {};
  79. for( var idx in drillability )
  80. {
  81. drillabilityJSON[drillability[idx].item] = drillability[idx];
  82. this.m_referenceInfoObject[drillability[idx].item] = true;
  83. }
  84. return drillabilityJSON;
  85. };
  86. RAPReportInfo.prototype._addFilterReferences = function(filters) {
  87. //Filters....
  88. for( var idx in filters ) {
  89. this.m_referenceInfoObject[filters[idx].item] = true;
  90. if (filters[idx].type==="contextSlice" && filters[idx].hierarchyName) {
  91. //context slices can be referenced by hierarchy name.
  92. this.m_referenceInfoObject[filters[idx].hierarchyName] = true;
  93. }
  94. }
  95. };
  96. RAPReportInfo.prototype._addSliderReferences = function(sliders) {
  97. //Sliders...
  98. for( var idx in sliders ) {
  99. this.m_referenceInfoObject[sliders[idx].name] = true; //For sliders, its the name attribute not the item attribute.
  100. }
  101. };
  102. RAPReportInfo.prototype._addNonVisibleReferences = function(oReportLevelProperties) {
  103. //Non-visible items...
  104. if(oReportLevelProperties && oReportLevelProperties.nonVisibleFiltersMemberItemInfo){
  105. for(var i = 0;i<oReportLevelProperties.nonVisibleFiltersMemberItemInfo.length; i++){
  106. this.m_referenceInfoObject[oReportLevelProperties.nonVisibleFiltersMemberItemInfo[i]]=true;
  107. }
  108. }
  109. };
  110. RAPReportInfo.prototype.isReferenced = function(item) {
  111. return (this.m_referenceInfoObject[item]) ? true : false;
  112. };
  113. /**
  114. * Return drillability based on containerLID and item name
  115. */
  116. RAPReportInfo.prototype.getDrillability = function( sContainerLID, sItemName) {
  117. if( !sItemName )
  118. {
  119. return this.m_containerInfoJSON[sContainerLID].m_drillabilityJSON;
  120. }
  121. else
  122. {
  123. return this.m_containerInfoJSON[sContainerLID].m_drillabilityJSON[ sItemName ];
  124. }
  125. };
  126. RAPReportInfo.prototype.getContainers = function()
  127. {
  128. return this.m_containerInfoJSON;
  129. };
  130. RAPReportInfo.prototype.getContainer = function(lid) {
  131. return this.m_containerInfoJSON[lid];
  132. };
  133. RAPReportInfo.prototype.getContainerIds = function(containerType) {
  134. var containerIds = [];
  135. for (containerName in this.m_containerInfoJSON) {
  136. var container = this.m_containerInfoJSON[containerName];
  137. if (container && container.displayTypeId == containerType) {
  138. containerIds.push(container.container);
  139. }
  140. }
  141. return containerIds;
  142. };
  143. /**
  144. * Returns the container based on position in the report
  145. */
  146. RAPReportInfo.prototype.getContainerFromPos = function( iPos )
  147. {
  148. return this.m_reportInfoJSON.containers[iPos];
  149. };
  150. RAPReportInfo.prototype.getReportLevelProperties = function()
  151. {
  152. return this.m_reportInfoJSON.reportLevelProperties;
  153. };
  154. /**
  155. * Return itemInfo based on containerLID and item name
  156. */
  157. RAPReportInfo.prototype.getItemInfo = function( sContainerLID, sItemName) {
  158. if( !sItemName )
  159. {
  160. return this.m_containerInfoJSON[sContainerLID].m_itemInfoJSON;
  161. }
  162. if( this.m_containerInfoJSON[sContainerLID] ){
  163. return this.m_containerInfoJSON[sContainerLID].m_itemInfoJSON[sItemName];
  164. }
  165. return null;
  166. };
  167. /**
  168. * @param {String} itemName This is a string parameter
  169. */
  170. RAPReportInfo.prototype.isReportLevel_nonVisibleFilterItem = function(itemName){
  171. if(itemName && itemName.length > 0){
  172. var oReportLevelProperties = this.m_reportInfoJSON.reportLevelProperties;
  173. if(oReportLevelProperties){
  174. if(oReportLevelProperties && oReportLevelProperties.nonVisibleFiltersMemberItemInfo){
  175. for(var i = 0;i<oReportLevelProperties.nonVisibleFiltersMemberItemInfo.length; i++){
  176. if(itemName === oReportLevelProperties.nonVisibleFiltersMemberItemInfo[i]){
  177. return true;
  178. }
  179. }
  180. }
  181. }
  182. }
  183. return false;
  184. }
  185. /**
  186. * Return true if this container is a child container
  187. * (childContainers have a parentContainer, parentContainers do not)
  188. */
  189. RAPReportInfo.prototype.isChildContainer = function(lid) {
  190. return ((this.m_containerInfoJSON[lid] &&
  191. this.m_containerInfoJSON[lid].parentContainer) ? true : false);
  192. };
  193. /**
  194. * Return an object with item details, or returns null if item is not found
  195. *
  196. * obj = {
  197. * item,
  198. * hun,
  199. * lid,
  200. * queryName
  201. * }
  202. */
  203. RAPReportInfo.prototype.getItemDetails = function(sItemName, sHun) {
  204. var obj = null;
  205. for (var lid in this.m_containerInfoJSON) {
  206. var oItem = this.getItemInfo(lid, sItemName);
  207. if(oItem && oItem.hun === sHun) {
  208. obj = {};
  209. obj.item = oItem.item;
  210. if (oItem.hun) {
  211. obj.hun = oItem.hun;
  212. }
  213. obj.lid= lid;
  214. obj.queryName = oItem.queryName;
  215. break;
  216. }
  217. }
  218. return (obj)? obj: null;
  219. };
  220. /**
  221. * Returns the object getItemDetails function returns, or returns null if item is not found
  222. */
  223. RAPReportInfo.prototype.getItemDetailsByHun = function(sHun) {
  224. var sItemName = null;
  225. // find item with same hun
  226. for (var lid in this.m_containerInfoJSON) {
  227. var oItems = this.getItemInfo(lid);
  228. for (var sName in oItems) {
  229. var oItem = oItems[sName];
  230. if (oItem.hun === sHun) {
  231. sItemName = sName;
  232. break;
  233. }
  234. }
  235. }
  236. return (sItemName? this.getItemDetails(sItemName, sHun): null);
  237. };
  238. /**
  239. * If item does not have 'hun' info, find and set from meta data.
  240. * If found,
  241. * updates it in both m_containerInfoJSON and m_reportInfoJSON,
  242. * updates string value of envParams['rapReportInfo'] as it is still in use.
  243. *
  244. * This function is called from CognosViewer.updateRapReportInfo
  245. */
  246. RAPReportInfo.prototype._populateHun = function(oCV) {
  247. if (oCV) {
  248. var oCCDManager = oCV.getSelectionController().getCCDManager();
  249. var envParams = oCV.envParams;
  250. var oldRAPReportInfo = oCV.getRAPReportInfo()
  251. var bUpdateEnvParams = false;
  252. for (var lid in this.m_containerInfoJSON) {
  253. var oItemInfo = this.m_containerInfoJSON[lid].m_itemInfoJSON;
  254. for (var sItemName in oItemInfo) {
  255. var oItem = oItemInfo[sItemName];
  256. /**
  257. * sometimes the report is a mix of low-level and high-level spec, therefore,
  258. * need to loop to make sure all the hun info are obtained
  259. */
  260. if (oItem.hun) {
  261. continue;
  262. }
  263. var sHun = this.getHUNForItem( oItem, oCCDManager, lid, oldRAPReportInfo );
  264. if ( sHun ) {
  265. oItem.hun = sHun;
  266. bUpdateEnvParams = true;
  267. }
  268. }
  269. }
  270. /**
  271. * need to update the rapReportInfo in the envParams with HUN info as it
  272. * does not have it.
  273. */
  274. if (bUpdateEnvParams && typeof JSON != "undefined" && JSON != null && JSON.stringify) {
  275. envParams["rapReportInfo"] = JSON.stringify(this.m_reportInfoJSON);
  276. }
  277. }
  278. };
  279. RAPReportInfo.prototype.getHUNForItem = function( oItem, oCCDManager, lid, oldRAPReportInfo ) {
  280. var sHun = this.getHUNFromCCDManager( oCCDManager, oItem );
  281. var oldItem = null;
  282. if( !sHun && oldRAPReportInfo ) {
  283. /**
  284. * Get the hun from previous report info - this should only happen in the case of delayed
  285. * viewer loading.
  286. */
  287. oldItem = oldRAPReportInfo.getItemInfo( lid, oItem.item );
  288. if( oldItem )
  289. {
  290. sHun = oldItem.hun;
  291. }
  292. }
  293. return sHun;
  294. };
  295. RAPReportInfo.prototype.getHUNFromCCDManager = function( oCCDManager, oItem ) {
  296. var oQueryCtxidMap = {};
  297. var sHUN = null;
  298. var queryId = this._findQueryMetadataId(oCCDManager, oQueryCtxidMap, oItem.queryName);
  299. if (queryId) {
  300. sHUN = oCCDManager.GetHUNForRDI(oItem.item, queryId);
  301. }
  302. return sHUN;
  303. };
  304. RAPReportInfo.prototype._findQueryMetadataId = function(oCCDManager, oMap, queryName) {
  305. if (oMap[queryName]) {
  306. return oMap[queryName];
  307. }
  308. var ctxId = oCCDManager.GetMetadataIdForQueryName(queryName);
  309. if (ctxId) {
  310. oMap[queryName] = ctxId;
  311. return ctxId;
  312. }
  313. return null;
  314. };
  315. RAPReportInfo.prototype.isPromptPart = function() {
  316. if (this.m_bPromptPart === null) {
  317. if (this.m_reportInfoJSON.reportLevelProperties &&
  318. this.m_reportInfoJSON.reportLevelProperties.promptWidget === true) {
  319. this.m_bPromptPart = true;
  320. } else {
  321. this.m_bPromptPart = false;
  322. }
  323. }
  324. return this.m_bPromptPart;
  325. };
  326. RAPReportInfo.prototype.getContainerCount = function() {
  327. return this.m_iContainerCount;
  328. };
  329. /**
  330. * Returns true if there's only one container and reportLevelProperties.singleContainerReport is set to true
  331. */
  332. RAPReportInfo.prototype.isSingleContainer = function() {
  333. if (this.m_bSingleContainer === null) {
  334. if (this.m_iContainerCount === 1 && this.m_reportInfoJSON.reportLevelProperties && this.m_reportInfoJSON.reportLevelProperties.singleContainerReport === true) {
  335. this.m_bSingleContainer = true;
  336. }
  337. else {
  338. this.m_bSingleContainer = false;
  339. }
  340. }
  341. return this.m_bSingleContainer;
  342. };
  343. /**
  344. * Returns true is reportLevelProperties.detailFilteringDisabled is set to true
  345. */
  346. RAPReportInfo.prototype.isDetailFilteringDisabled = function() {
  347. if (this.m_bDetailFilteringDisabled === null) {
  348. if (this.m_reportInfoJSON.reportLevelProperties && this.m_reportInfoJSON.reportLevelProperties.detailFilteringDisabled === true) {
  349. this.m_bDetailFilteringDisabled = true;
  350. }
  351. else {
  352. this.m_bDetailFilteringDisabled = false;
  353. }
  354. }
  355. return this.m_bDetailFilteringDisabled;
  356. };
  357. RAPReportInfo.prototype.getPassTrackingtoBUA = function() {
  358. if (this.m_bPassTrackingToBUA === null) {
  359. if (this.m_reportInfoJSON.reportLevelProperties && this.m_reportInfoJSON.reportLevelProperties.shouldNotPassTrackingtoBUA === true) {
  360. this.m_bPassTrackingToBUA = false;
  361. }
  362. else {
  363. this.m_bPassTrackingToBUA = true;
  364. }
  365. }
  366. return this.m_bPassTrackingToBUA;
  367. };
  368. /**
  369. * Get the list of HUNs that have been drilled on
  370. */
  371. RAPReportInfo.prototype.getDrilledOnHUNs = function() {
  372. if (!this.m_aDrilledOnHUNs && this.m_reportInfoJSON.reportLevelProperties && this.m_reportInfoJSON.reportLevelProperties.drilledOnHUNs) {
  373. this.m_aDrilledOnHUNs = this.m_reportInfoJSON.reportLevelProperties.drilledOnHUNs;
  374. }
  375. return this.m_aDrilledOnHUNs;
  376. };
  377. /**
  378. * Gets a comma separated string of display types
  379. * @param skipContainerLID - if specified will return a comma separated list of display types
  380. * for all the containers except the one that matches the lid
  381. */
  382. RAPReportInfo.prototype.getDisplayTypes = function(skipContainerLID) {
  383. if (this.m_sDisplayTypes === null || skipContainerLID) {
  384. var sDisplayTypes = "";
  385. var displayTypesArray = [];
  386. for (var lid in this.m_containerInfoJSON) {
  387. if (!skipContainerLID || lid != skipContainerLID) {
  388. displayTypesArray.push(this.m_containerInfoJSON[lid].displayTypeId);
  389. }
  390. }
  391. sDisplayTypes = displayTypesArray.join(",");
  392. // if empty, check for prompt widget
  393. if (sDisplayTypes == "" && this.isPromptPart()) {
  394. sDisplayTypes = "promptWidget";
  395. }
  396. // we should only cache the list of display types if it's the full list (didn't skip any containers)
  397. if (!skipContainerLID) {
  398. this.m_sDisplayTypes = sDisplayTypes;
  399. }
  400. return sDisplayTypes;
  401. }
  402. return this.m_sDisplayTypes;
  403. };
  404. RAPReportInfo.prototype.isChart = function(lid) {
  405. var id = lid.toLowerCase();
  406. return id != 'mapchart' && id.match('chart$') == 'chart';
  407. };
  408. /**
  409. * Returns true if the container with the lid is a visualization (ie: type viz)
  410. */
  411. RAPReportInfo.prototype.isViz = function(lid) {
  412. if (this.m_containerInfoJSON[lid]) {
  413. var displayTypeId = this.m_containerInfoJSON[lid].displayTypeId;
  414. if (displayTypeId) {
  415. return (displayTypeId.toLowerCase()=='viz');
  416. }
  417. }
  418. return false;
  419. };
  420. /**
  421. * Returns true|false if the container with the lid is an interactive container
  422. */
  423. RAPReportInfo.prototype.isInteractiveDataContainer = function(lid) {
  424. var result = false;
  425. if (this.m_containerInfoJSON[lid]) {
  426. var displayTypeId = this.m_containerInfoJSON[lid].displayTypeId;
  427. if (displayTypeId) {
  428. var id = displayTypeId.toLowerCase();
  429. result = id == 'crosstab' || id == 'list' || id== 'viz' || this.isChart(id);
  430. }
  431. }
  432. return result;
  433. };
  434. /**
  435. * Returns true|false depending if there's an interactive report container (list/crosstab/chart) in the report
  436. */
  437. RAPReportInfo.prototype.containsInteractiveDataContainer = function() {
  438. if (this.m_bContainsInteractiveDataContainer == null) {
  439. this.m_bContainsInteractiveDataContainer = false;
  440. for (var lid in this.m_containerInfoJSON) {
  441. if (this.isInteractiveDataContainer(lid)) {
  442. this.m_bContainsInteractiveDataContainer = true;
  443. break;
  444. }
  445. }
  446. }
  447. return this.m_bContainsInteractiveDataContainer;
  448. };
  449. /**
  450. * Returns true if any of the containers contains filter information
  451. */
  452. RAPReportInfo.prototype.containsFilters = function() {
  453. return this.m_bContainsFilters;
  454. };
  455. /**
  456. * Returns the filter object that matches the refDataItem passed in. If bWithLabel is set to true, then
  457. * the filter object will only be returned if it contains an itemLabel.
  458. *
  459. * If no match is found then null is returned.
  460. */
  461. RAPReportInfo.prototype.getFilterObject = function(refDataItem, bWithLabel) {
  462. for (var lid in this.m_containerInfoJSON) {
  463. var filterObj = this.getFilterObjectFromContainer(lid, refDataItem, bWithLabel);
  464. if (filterObj) {
  465. return filterObj;
  466. }
  467. }
  468. return null;
  469. };
  470. /**
  471. * Returns the filter object that matches the refDataItem passed in for the specified container.
  472. * If bWithLabel is set to true, then the filter object will only be returned if it contains an itemLabel.
  473. *
  474. * If no match is found then null is returned.
  475. */
  476. RAPReportInfo.prototype.getFilterObjectFromContainer = function(lid, refDataItem, bWithLabel) {
  477. var oContainer = this.m_containerInfoJSON[lid];
  478. if (oContainer && oContainer.filter) {
  479. var length = oContainer.filter.length;
  480. // This container has filters....does it filter an item with the same refDataItem?
  481. for (var i = 0; i < length; ++i) {
  482. var filterItem = oContainer.filter[i];
  483. if (refDataItem == filterItem.item) {
  484. if (!bWithLabel || (filterItem.itemLabel && filterItem.itemLabel.length > 0) ) {
  485. return filterItem;
  486. }
  487. }
  488. }
  489. }
  490. return null;
  491. };
  492. /**
  493. * Returns the name of the slider or the item of the filter that has same HUN with the specified unique name.
  494. *
  495. * If no match is found then null is returned.
  496. *
  497. * @param uniqueName a mun, lun or hun can be passed
  498. */
  499. RAPReportInfo.prototype.hunHasFilterOrSlider = function(uniqueName) {
  500. if (!uniqueName) {
  501. return null;
  502. }
  503. for (var lid in this.m_containerInfoJSON) {
  504. var oContainer = this.m_containerInfoJSON[lid];
  505. if (oContainer && oContainer.filter) {
  506. var length = oContainer.filter.length;
  507. for (var i = 0; i < length; ++i) {
  508. var filterItem = oContainer.filter[i];
  509. if (filterItem.HUN && uniqueName.indexOf(filterItem.HUN)==0) {
  510. return filterItem.item;
  511. }
  512. }
  513. }
  514. if (oContainer && oContainer.sliders) {
  515. var length = oContainer.sliders.length;
  516. for (var i = 0; i < length; ++i) {
  517. var sliderItem = oContainer.sliders[i];
  518. if (sliderItem.hun && uniqueName.indexOf(sliderItem.hun)==0) {
  519. return sliderItem.name;
  520. }
  521. }
  522. }
  523. }
  524. return null;
  525. };
  526. RAPReportInfo.prototype.hasSlider = function(){
  527. return this.m_bContainsSlider;
  528. };
  529. /**
  530. * Returns a map of sliders for this report indexed by ClientID
  531. */
  532. RAPReportInfo.prototype.collectSliderSetFromReportInfo = function() {
  533. var reportInfoSliderIDs = {};
  534. for (var lid in this.m_containerInfoJSON) {
  535. var sliders = this.m_containerInfoJSON[lid].sliders;
  536. if(sliders) {
  537. for(var sliderIndex = 0; sliderIndex < sliders.length; ++sliderIndex) {
  538. var sliderClientID = sliders[sliderIndex].clientId;
  539. reportInfoSliderIDs[sliderClientID] = sliders[sliderIndex];
  540. }
  541. }
  542. }
  543. return reportInfoSliderIDs;
  544. };
  545. /**
  546. * When the advanced server property VIEWER_CW_RAP_TIMER is set, this block of info is populated
  547. * with timing information about RAP server events that can be reported in the infobar.
  548. */
  549. RAPReportInfo.prototype._getEventTimings = function() {
  550. return (this.m_reportInfoJSON && this.m_reportInfoJSON.reportLevelProperties &&
  551. this.m_reportInfoJSON.reportLevelProperties.eventTimings) ?
  552. this.m_reportInfoJSON.reportLevelProperties.eventTimings : null;
  553. };
  554. RAPReportInfo.prototype.destroy = function() {
  555. GUtil.destroyProperties(this);
  556. };