1 /**
  2  * @fileOverview
  3  * @author <a href="https://www.labkey.org">LabKey</a> (<a href="mailto:info@labkey.com">info@labkey.com</a>)
  4  * @license Copyright (c) 2012-2017 LabKey Corporation
  5  * <p/>
  6  * Licensed under the Apache License, Version 2.0 (the "License");
  7  * you may not use this file except in compliance with the License.
  8  * You may obtain a copy of the License at
  9  * <p/>
 10  * http://www.apache.org/licenses/LICENSE-2.0
 11  * <p/>
 12  * Unless required by applicable law or agreed to in writing, software
 13  * distributed under the License is distributed on an "AS IS" BASIS,
 14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15  * See the License for the specific language governing permissions and
 16  * limitations under the License.
 17  * <p/>
 18  */
 19 
 20 /**
 21  * @namespace Report static class that allows programmatic manipulation of reports and their underlying engines.
 22  */
 23 LABKEY.Report = new function(){
 24     /**
 25      * Private function to decode json output parameters into objects
 26      * @param config
 27      * @return {Mixed}
 28      */
 29     function getExecuteSuccessCallbackWrapper(callbackFn, scope)
 30     {
 31         return LABKEY.Utils.getCallbackWrapper(function(data, response, options){
 32             if (data && data.outputParams) {
 33                 for (var idx = 0; idx < data.outputParams.length; idx++) {
 34                     var param = data.outputParams[idx];
 35                     if (param.type == 'json') {
 36                         param.value = LABKEY.Utils.decode(param.value);
 37                     }
 38                 }
 39             }
 40             if (callbackFn)
 41                 callbackFn.call(scope || this, data, options, response);
 42         }, this);
 43     }
 44 
 45     function populateParams(config, isReport)
 46     {
 47         var execParams = {};
 48 
 49         // fill in these parameters if we are executing a report
 50         if (isReport)
 51         {
 52 
 53             if (config.reportId)
 54                 execParams["reportId"] = config.reportId;
 55 
 56             if (config.reportName)
 57                 execParams["reportName"] = config.reportName;
 58 
 59             if (config.schemaName)
 60                 execParams["schemaName"] = config.schemaName;
 61 
 62             if (config.queryName)
 63                 execParams["queryName"] = config.queryName;
 64         }
 65         else
 66         {
 67             if (config.functionName)
 68                 execParams["functionName"] = config.functionName;
 69         }
 70 
 71         // the rest are common
 72         if (config.reportSessionId)
 73             execParams["reportSessionId"] = config.reportSessionId;
 74 
 75         // bind client input params to our parameter map
 76         for (var key in config.inputParams)
 77         {
 78             execParams["inputParams[" + key + "]"] = config.inputParams[key];
 79         }
 80 
 81         return execParams;
 82     }
 83 
 84     function _execute(config, isReport)
 85     {
 86         return LABKEY.Ajax.request({
 87             url: LABKEY.ActionURL.buildURL("reports", "execute", config.containerPath),
 88             method: 'POST',
 89             success: getExecuteSuccessCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope),
 90             failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true),
 91             jsonData : populateParams(config, isReport)
 92         });
 93     }
 94 
 95     //public interface
 96     /** @scope LABKEY.Report */
 97     return {
 98         /**
 99          * Creates a new report session which can be used across multiple report requests.  For example,
100          * this allows an R script to setup an R environment and then use this environment in
101          * subsequent R scripts.
102          * @param {Object} config A configuration object with the following properties.
103          * @param {Object} config.clientContext Client supplied identifier returned in a call to getSessions()
104          * @param {Function} config.success The function to call with the resulting information.
105          * This function will be passed a single parameter of type object, which will have the following
106          * properties:
107          * <ul>
108          *  <li>reportSessionId: A unique identifier that represents the new underlying report session, a String</li>
109          * </ul>
110          * @param {Function} [config.failure] A function to call if an error occurs. This function
111          * will receive one parameter of type object with the following properties:
112          * <ul>
113          *  <li>exception: The exception message.</li>
114          * </ul>
115          * @param {String} [config.containerPath] The container in which to make the request (defaults to current container)
116          * @param {Object} [config.scope] The scope to use when calling the callbacks (defaults to this).
117          */
118         createSession : function(config) {
119             var containerPath = config && config.containerPath;
120             var createParams = {};
121             createParams["clientContext"] = config.clientContext;
122 
123             LABKEY.Ajax.request({
124                 url: LABKEY.ActionURL.buildURL("reports", "createSession", containerPath ),
125                 method: 'POST',
126                 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope),
127                 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true),
128                 jsonData : createParams
129             });
130         },
131 
132         /**
133          * Deletes an underlying report session
134          *
135          * @param {Object} config A configuration object with the following properties.
136          * @param {String} config.reportSessionId Identifier for the report session to delete.
137          * @param {Function} config.success The function to call if the operation is successful.
138          * @param {Function} [config.failure] A function to call if an error occurs. This function
139          * will receive one parameter of type object with the following properties:
140          * <ul>
141          *  <li>exception: The exception message.</li>
142          * </ul>
143          * @param {String} [config.containerPath] The container in which to make the request (defaults to current container)
144          * @param {Object} [config.scope] The scope to use when calling the callbacks (defaults to this).
145          */
146         deleteSession : function(config) {
147             var params = { reportSessionId : config.reportSessionId };
148             LABKEY.Ajax.request({
149                 url: LABKEY.ActionURL.buildURL("reports", "deleteSession", config.containerPath),
150                 method: 'POST',
151                 params: params,
152                 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope, false),
153                 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true)
154             });
155         },
156 
157         /**
158          * Returns a list of report sessions created via createSession
159          *
160          * @param {Object} config A configuration object with the following properties.
161          * @param {Function} config.success The function to call if the operation is successful.  This function will
162          * receive an object with the following properties
163          * <ul>
164          *     <li>reportSessions:  a reportSession[] of any sessions that have been created by the client
165          * </ul>
166          *
167          * @param {Function} [config.failure] A function to call if an error occurs. This function
168          * will receive one parameter of type object with the following properties:
169          * <ul>
170          *  <li>exception: The exception message.</li>
171          * </ul>
172          * @param {String} [config.containerPath] The container in which to make the request (defaults to current container)
173          * @param {Object} [config.scope] The scope to use when calling the callbacks (defaults to this).
174          */
175         getSessions : function(config) {
176             LABKEY.Ajax.request({
177                 url: LABKEY.ActionURL.buildURL("reports", "getSessions", config.containerPath),
178                 method: 'POST',
179                 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope, false),
180                 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true)
181             });
182         },
183 
184         /**
185          * Executes a report script
186          *
187          * @param {Object} config A configuration object with the following properties.
188          * @param {String} [config.containerPath] The container in which to make the request (defaults to current container)
189          * @param {Object} [config.scope] The scope to use when calling the callbacks (defaults to this).
190          * @param {String} config.reportId Identifier for the report to execute
191          * @param {String} [config.reportName] name of the report to execute if the id is unknown
192          * @param {String} [config.schemaName] schema to which this report belongs (only used if reportName is used)
193          * @param {String} [config.queryName] query to which this report belongs (only used if reportName is used)
194          * @param {String} [config.reportSessionId] Execute within the existsing report session.
195          * @param {String} [config.inputParams] An object with properties for input parameters.
196          * @param {Function} config.success The function to call if the operation is successful.  This function will
197          * receive an object with the following properties
198          * <ul>
199          *     <li>console:  a string[] of information written by the script to the console</li>
200          *     <li>error:  any exception thrown by the script that halted execution</li>
201          *     <li>ouputParams:  an outputParam[] of any output parameters (imgout, jsonout, etc) returned by the script</li>
202          * </ul>
203          * @param {Function} [config.failure] A function to call if an error preventing script execution occurs.
204          * This function will receive one parameter of type object with the following properties:
205          * <ul>
206          *  <li>exception: The exception message.</li>
207          * </ul>
208          */
209         execute : function(config) {
210             if (!config)
211                 throw "You must supply a config object to call this method.";
212 
213             if (!config.reportId && !config.reportName)
214                 throw "You must supply a value for the reportId or reportName config property.";
215 
216             return _execute(config, true);
217         },
218 
219         /**
220          * Executes a single method available in the namespace of a previously created session context.
221          *
222          * @param {Object} config A configuration object with the following properties.
223          * @param {String} [config.containerPath] The container in which to make the request (defaults to current container)
224          * @param {Object} [config.scope] The scope to use when calling the callbacks (defaults to this).
225          * @param {String} [config.functionName] The name of the function to execute
226          * @param {String} [config.reportSessionId] Execute within the existsing report session.
227          * @param {String} [config.inputParams] An object with properties for input parameters.
228          * @param {Function} config.success The function to call if the operation is successful.  This function will
229          * receive an object with the following properties
230          * <ul>
231          *     <li>console:  a string[] of information written by the script to the console</li>
232          *     <li>error:  any exception thrown by the script that halted execution</li>
233          *     <li>ouputParams:  an outputParam[] of any output parameters (imgout, jsonout, etc) returned by the script</li>
234          * </ul>
235          * @param {Function} [config.failure] A function to call if an error preventing script execution occurs.
236          * This function will receive one parameter of type object with the following properties:
237          * <ul>
238          *  <li>exception: The exception message.</li>
239          * </ul>
240          */
241         executeFunction : function(config) {
242             if (!config)
243                 throw "You must supply a config object to call this method.";
244 
245             if (!config.functionName)
246                 throw "You must supply a value for the functionName config property.";
247 
248             return _execute(config, false);
249         }
250     };
251 };
252