ViewerLoadManager.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*
  2. *+------------------------------------------------------------------------+
  3. *| Licensed Materials - Property of IBM
  4. *| IBM Cognos Products: Viewer
  5. *| (C) Copyright IBM Corp. 2011, 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. * This class manages the loading state of the Viewer. In particular:
  14. * * viewerLoadInitiated - has the post to the server been made to
  15. * retrieve the viewer?
  16. * * canRunReports - for actions which need a subsequent report
  17. * run (i.e. using the modifyReport action), has the report been run?
  18. * * isViewerReady - has the viewer been loaded and all outstanding
  19. * callbacks in the queue been serviced?
  20. */
  21. function ViewerLoadManager(widget) {
  22. this.m_oWidget = widget;
  23. this.m_oDelayedLoadingContext = new DelayedLoadingContext();
  24. this.m_aQueue = [];
  25. this.m_fOnEmptyCallback = null;
  26. this.m_bPendingRequest = false;
  27. this.m_bViewerLoadInitiated = false;
  28. this.m_bCanRunReports = false;
  29. }
  30. /**
  31. * Invoke to indicate that the load of the Viewer object
  32. * has been initiated (and therefore shouldn't be repeated).
  33. */
  34. ViewerLoadManager.prototype.viewerLoadInitiated = function() {
  35. this.m_bViewerLoadInitiated = true;
  36. };
  37. /**
  38. * @return whether the load of the Viewer object has yet been
  39. * initiated.
  40. */
  41. ViewerLoadManager.prototype.isViewerLoadInitiated = function() {
  42. return this.m_bViewerLoadInitiated;
  43. };
  44. /**
  45. * @return true iff a report has already been run, so the viewer
  46. * is ready to subsequently run the report
  47. */
  48. ViewerLoadManager.prototype.canRunReports = function() {
  49. return this.m_bCanRunReports;
  50. };
  51. /**
  52. * Invoke to indicate a report run is being initiated.
  53. * The canRunReport flag will be set on the subsequent response
  54. * from the server.
  55. */
  56. ViewerLoadManager.prototype.runningReport = function() {
  57. if(!this.m_bCanRunReports) {
  58. this._queue( { fCallback: dojo.hitch(this, function() {
  59. this.m_bCanRunReports = true;
  60. return false;
  61. })});
  62. }
  63. };
  64. /**
  65. * @return true iff the Viewer has been loaded and is ready for use
  66. */
  67. ViewerLoadManager.prototype.isViewerReady = function() {
  68. if(!this.isViewerLoaded()) {
  69. return false;
  70. }
  71. //Queue should be empty, no pending onEmpty callback, and no requests in progress
  72. if(!this._isEmpty() || this.m_fOnEmptyCallback || this.m_bPendingRequest) {
  73. return false;
  74. }
  75. return true;
  76. };
  77. /**
  78. * @return true iff Viewer is loaded
  79. */
  80. ViewerLoadManager.prototype.isViewerLoaded = function() {
  81. //Need a viewer in memory
  82. var oCV = this.m_oWidget.getViewerObject();
  83. if(!oCV) {
  84. return false;
  85. }
  86. if(this.m_oWidget.isLiveReport()) {
  87. var sStatus = oCV.getStatus();
  88. return sStatus === "complete" || sStatus === "prompting" || sStatus === "fault";
  89. }
  90. return true;
  91. };
  92. /**
  93. * Invokes f when there is a viewer ready. f must return true
  94. * iff it sent a request to the server
  95. * (i.e. processDelayedEventsQueue will be invoked), false otherwise.
  96. * If sGroupId is specified, then if there are consecutive callbacks with the
  97. * same group id, only the last one will be executed. *
  98. * @return true iff f was invoked synchronously (i.e. before
  99. * _runWhenHasViewer terminated), false otherwise.
  100. */
  101. ViewerLoadManager.prototype.runWhenHasViewer = function(f, sGroupId) {
  102. if(this.isViewerReady()) {
  103. this._run(f);
  104. return true;
  105. } else {
  106. var oCallback = {fCallback: f};
  107. if(sGroupId) {
  108. oCallback.sGroupId = sGroupId;
  109. }
  110. this._queue(oCallback);
  111. //If Viewer hasn't started loading yet, load without running the report.
  112. if(!this.m_bViewerLoadInitiated) {
  113. this.getDelayedLoadingContext().setForceRunReport(true);
  114. this.m_oWidget.setRunReportOption(false);
  115. this.m_oWidget.postReport(null);
  116. }
  117. return false;
  118. }
  119. };
  120. /**
  121. * Invoke to process the queue of callbacks waiting for a
  122. * loaded viewer. Will process callbacks until one needs to
  123. * block until a response from the server is received.
  124. */
  125. ViewerLoadManager.prototype.processQueue = function() {
  126. //Clear pending request flag - the last request has returned
  127. this.m_bPendingRequest = false;
  128. //Service each function in the queue until one goes to the server,
  129. //then stop servicing queue. Queue servicing will resume upon
  130. //response from the server.
  131. var bServerRequest = false;
  132. while(!bServerRequest && !this._isEmpty()) {
  133. var oCallback = this.m_aQueue.shift();
  134. //If this entry has a group id, check if there's a later entry with the
  135. //same group id. Only run the later one.
  136. while(oCallback.sGroupId && !this._isEmpty() && this.m_aQueue[0].sGroupId === oCallback.sGroupId) {
  137. oCallback = this.m_aQueue.shift();
  138. }
  139. bServerRequest = this._run(oCallback.fCallback);
  140. }
  141. //onEmptyCallback is treated like the perpetually last entry in
  142. //the queue. It is only invoked if the rest of the queue is empty,
  143. //and there is no pending request to the server.
  144. //Once invoked, it is cleared.
  145. if(this._isEmpty() && !bServerRequest && this.m_fOnEmptyCallback) {
  146. var fCallback = this.m_fOnEmptyCallback;
  147. this.m_fOnEmptyCallback = null;
  148. fCallback();
  149. }
  150. };
  151. ViewerLoadManager.prototype._run = function(f) {
  152. var bServerRequest = f.call();
  153. if(bServerRequest) {
  154. //Set pending request flag.
  155. //Don't allow simultaneous requests because
  156. //the second will clobber the first.
  157. this.m_bPendingRequest = true;
  158. }
  159. return bServerRequest;
  160. };
  161. ViewerLoadManager.prototype._isEmpty = function() {
  162. return !this.m_aQueue.length;
  163. };
  164. ViewerLoadManager.prototype._queue = function(oEntry) {
  165. this.m_aQueue.push(oEntry);
  166. };
  167. /**
  168. * Set the callback to be invoked when the queue is empty. Once
  169. * invoked, this member is cleared (i.e. only invoked once).
  170. */
  171. ViewerLoadManager.prototype.setOnEmptyCallback = function(fCallback) {
  172. this.m_fOnEmptyCallback = fCallback;
  173. };
  174. /**
  175. * @return the DelayedLoadingContext
  176. */
  177. ViewerLoadManager.prototype.getDelayedLoadingContext = function() {
  178. return this.m_oDelayedLoadingContext;
  179. };