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) 2008-2018 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 Assay static class to retrieve read-only assay definitions.
 22  * @see LABKEY.Experiment
 23  */
 24 LABKEY.Assay = new function()
 25 {
 26     function getAssays(config)
 27     {
 28         //check for old-style separate arguments
 29         if(arguments.length > 1) {
 30             config = {
 31                 success: arguments[0],
 32                 failure: arguments[1],
 33                 parameters: arguments[2],
 34                 containerPath: arguments[3]
 35             };
 36         }
 37 
 38         moveParameter(config, "id");
 39         moveParameter(config, "type");
 40         moveParameter(config, "name");
 41 
 42         LABKEY.Ajax.request({
 43             url : LABKEY.ActionURL.buildURL("assay", "assayList", config.containerPath),
 44             method : 'POST',
 45             success: LABKEY.Utils.getOnSuccess(config),
 46             failure: LABKEY.Utils.getOnFailure(config),
 47             scope: config.scope || this,
 48             jsonData : config.parameters,
 49             headers : {
 50                 'Content-Type' : 'application/json'
 51             }
 52         });
 53     }
 54 
 55     function getSuccessCallbackWrapper(successCallback, scope)
 56     {
 57         return LABKEY.Utils.getCallbackWrapper(function(data, response){
 58             if(successCallback)
 59                 successCallback.call(this, data.definitions, response);
 60         }, (scope || this));
 61     }
 62 
 63     function moveParameter(config, param)
 64     {
 65         if (!config.parameters) config.parameters = {};
 66         if (config[param])
 67         {
 68             config.parameters[param] = config[param];
 69             delete config[param];
 70         }
 71     }
 72 
 73     /** @scope LABKEY.Assay */
 74     return {
 75 
 76 	/**
 77 	* Gets all assays.
 78 	* @param {Function} config.success Required. Function called when the
 79 			"getAll" function executes successfully.  Will be called with the argument: 
 80 			{@link LABKEY.Assay.AssayDesign[]}.
 81     * @param {Object} config An object which contains the following configuration properties.
 82 	* @param {Object} [config.scope] The scope to be used for the success and failure callbacks
 83     * @param {Function} [config.failure] Function called when execution of the "getAll" function fails.
 84 	* @param {String} [config.containerPath] The container path in which the requested Assays are defined.
 85 	*       If not supplied, the current container path will be used.
 86 	* @example Example:
 87 <pre name="code" class="xml">
 88 <script type="text/javascript">
 89 	function successHandler(assayArray) 
 90 	{ 
 91 		var html = ''; 
 92 		for (var defIndex = 0; defIndex < assayArray.length; defIndex ++) 
 93 		{ 
 94 			var definition = assayArray[defIndex ]; 
 95 			html += '<b>' + definition.type + '</b>: ' 
 96 				+ definition.name + '<br>'; 
 97 			for (var domain in definition.domains) 
 98 			{ 
 99 				html += '   ' + domain + '<br>'; 
100 				var properties = definition.domains[domain]; 
101 				for (var propertyIndex = 0; propertyIndex 
102 					< properties.length; propertyIndex++) 
103 				{ 
104 					var property = properties[propertyIndex]; 
105 					html += '      ' + property.name + 
106 						' - ' + property.typeName + '<br>'; 
107 				} 
108 			} 
109 		} 
110 		document.getElementById('testDiv').innerHTML = html; 
111 	} 
112 
113 	function errorHandler(error) 
114 	{ 
115 		alert('An error occurred retrieving data.'); 
116 	}
117 	
118 	LABKEY.Assay.getAll({success: successHandler, failure: errorHandler});
119 </script>
120 <div id='testDiv'>Loading...</div>
121 </pre>
122 	  * @see LABKEY.Assay.AssayDesign
123 	  */
124         getAll : function(config)
125         {
126             if(arguments.length > 1) {
127                 config = {
128                     success: arguments[0],
129                     failure: arguments[1],
130                     parameters: {},
131                     containerPath: arguments[2]
132                 };
133             }
134 
135             config.success = getSuccessCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope);
136             getAssays(config);
137         },
138 	  /**
139 	  * Gets an assay by name.
140 	  * @param {Function(LABKEY.Assay.AssayDesign[])} config.success Function called when the "getByName" function executes successfully.
141       * @param {Object} config An object which contains the following configuration properties.
142 	  * @param {Function} [config.failure] Function called when execution of the "getByName" function fails.
143 	  * @param {Object} [config.scope] The scope to be used for the success and failure callbacks
144       * @param {String} [config.name] String name of the assay.
145 	  * @param {String} [config.containerPath] The container path in which the requested Assay is defined.
146 	  *       If not supplied, the current container path will be used.
147 	  * @see LABKEY.Assay.AssayDesign
148 	  */
149         getByName : function(config)
150         {
151             if(arguments.length > 1) {
152                 config = {
153                     success: arguments[0],
154                     failure: arguments[1],
155                     parameters: { name: arguments[2] },
156                     containerPath: arguments[3]
157                 };
158             }
159 
160             moveParameter(config, "name");
161             config.success = getSuccessCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope);
162             getAssays(config);
163         },
164 
165 	  /**
166 	  * Gets an assay by type.
167 	  * @param {Function(LABKEY.Assay.AssayDesign[])} config.success Function called
168 				when the "getByType" function executes successfully.
169       * @param {Object} config An object which contains the following configuration properties.
170 	  * @param {Function} [config.failure] Function called when execution of the "getByType" function fails.
171 	  * @param {Object} [config.scope] The scope to be used for the success and failure callbacks
172       * @param {String} config.type String name of the assay type.  "ELISpot", for example.
173 	  * @param {String} [config.containerPath] The container path in which the requested Assays are defined.
174 	  *       If not supplied, the current container path will be used.
175  	  * @see LABKEY.Assay.AssayDesign
176 	  */
177         getByType : function(config)
178         {
179             if(arguments.length > 1) {
180                 config = {
181                     success: arguments[0],
182                     failure: arguments[1],
183                     parameters: { type: arguments[2] },
184                     containerPath: arguments[3]
185                 };
186             }
187 
188             moveParameter(config, "type");
189             config.success = getSuccessCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope);
190             getAssays(config);
191         },
192 
193 	 /**
194 	 * Gets an assay by its ID.
195 	 * @param {Function(LABKEY.Assay.AssayDesign[])} config.success Function called
196 				when the "getById" function executes successfully.
197      * @param {Object} config An object which contains the following configuration properties.
198 	 * @param {Function} [config.failure] Function called when execution of the "getById" function fails.
199 	 * @param {Object} [config.scope] The scope to be used for the success and failure callbacks
200      * @param {Integer} config.id Unique integer ID for the assay.
201 	 * @param {String} [config.containerPath] The container path in which the requested Assay is defined.
202 	 *       If not supplied, the current container path will be used.
203 	 * @see LABKEY.Assay.AssayDesign
204 	 */
205         getById : function(config)
206         {
207             if(arguments.length > 1) {
208                 config = {
209                     success: arguments[0],
210                     failure: arguments[1],
211                     parameters: { id: arguments[2] },
212                     containerPath: arguments[3]
213                 };
214             }
215 
216             moveParameter(config, "id");
217             config.success = getSuccessCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope);
218             getAssays(config);
219         },
220 
221 
222         /**
223         * Select NAb assay data from an assay folder.
224         * @param {Object} config An object which contains the following configuration properties.
225          * @param {String} config.assayName  The name of the NAb assay design for which runs are to be retrieved.
226          * @param {Boolean} [config.includeStats]  Whether or not statistics (standard deviation, max, min, etc.) should
227          * be returned with calculations and well data.
228          * @param {Boolean} [config.includeWells]  Whether well-level data should be included in the response.
229          * @param {Boolean} [config.calculateNeut]  Whether neutralization should be calculated on the server.
230          * @param {Boolean} [config.includeFitParameters]  Whether the parameters used in the neutralization curve fitting calculation
231          * should be included in the response.
232         * @param {Function} config.success
233                 Function called when the "getNAbRuns" function executes successfully.
234                 This function will be called with the following arguments:
235                 <ul>
236                     <li>runs: an array of NAb run objects</li>
237                     <li>options: the options used for the AJAX request</li>
238                     <li>responseObj: the XMLHttpResponseObject instance used to make the AJAX request</li>
239                 </ul>
240         * @param {Function} [config.failure] Function called when execution of the "getNAbRuns" function fails.
241          *       This function will be called with the following arguments:
242  				<ul>
243  				    <li><b>errorInfo:</b> an object describing the error with the following fields:
244                          <ul>
245                              <li><b>exception:</b> the exception message</li>
246                              <li><b>exceptionClass:</b> the Java class of the exception thrown on the server</li>
247                              <li><b>stackTrace:</b> the Java stack trace at the point when the exception occurred</li>
248                          </ul>
249                      </li>
250                      <li><b>responseObj:</b> the XMLHttpResponseObject instance used to make the AJAX request</li>
251  				    <li><b>options:</b> the options used for the AJAX request</li>
252  				</ul>
253         *
254         * @param {Array} [config.filterArray] Array of objects created by {@link LABKEY.Filter.create}.
255         * @param {String} [config.sort]  String description of the sort.  It includes the column names
256         *       listed in the URL of a sorted data region (with an optional minus prefix to indicate
257         *       descending order). In the case of a multi-column sort, up to three column names can be
258         *       included, separated by commas.
259         * @param {String} [config.containerPath] The path to the container in which the schema and query are defined,
260         *       if different than the current container. If not supplied, the current container's path will be used.
261         * @param {Integer} [config.maxRows] The maximum number of runs to return from the server (defaults to 100).
262         *        If you want to return all possible rows, set this config property to -1.
263         * @param {Integer} [config.offset] The index of the first row to return from the server (defaults to 0).
264         *        Use this along with the maxRows config property to request pages of data.
265         * @param {Integer} [config.timeout] The maximum number of milliseconds to allow for this operation before
266         *       generating a timeout error (defaults to 30000).
267         */
268         getNAbRuns : function(config)
269         {
270             var dataObject = {};
271 
272             LABKEY.Utils.merge(dataObject, config);
273             if (config.sort)
274                 dataObject['query.sort'] = config.sort;
275             if(config.offset)
276                 dataObject['query.offset'] = config.offset;
277             if(config.maxRows)
278             {
279                 if(config.maxRows < 0)
280                     dataObject['query.showRows'] = "all";
281                 else
282                     dataObject['query.maxRows'] = config.maxRows;
283             }
284 
285             LABKEY.Filter.appendFilterParams(dataObject, config.filterArray);
286 
287             var successCallback = LABKEY.Utils.getOnSuccess(config);
288 
289             var requestConfig = {
290                 url : LABKEY.ActionURL.buildURL('nabassay', 'getNabRuns', config.containerPath),
291                 method : 'GET',
292                 success: LABKEY.Utils.getCallbackWrapper(function(data, response){
293                     if(successCallback)
294                         successCallback.call(config.scope, data.runs);
295                 }, this),
296                 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true),
297                 params : dataObject
298             };
299 
300             if (LABKEY.Utils.isDefined(config.timeout))
301                 requestConfig.timeout = config.timeout;
302 
303             LABKEY.Ajax.request(requestConfig);
304         },
305 
306 
307         /**
308         * Select detailed NAb information for runs with summary data that has been copied to a study folder.  Note that this
309          * method must be executed against the study folder containing the copied NAb summary data.
310          * @param {Object} config An object which contains the following configuration properties.
311          * @param {Array} config.objectIds The object Ids for the NAb data rows that have been copied to the study.
312          * @param {Boolean} [config.includeStats]  Whether or not statistics (standard deviation, max, min, etc.) should
313          * be returned with calculations and well data.
314          * @param {Boolean} [config.includeWells]  Whether well-level data should be included in the response.
315          * @param {Boolean} [config.calculateNeut]  Whether neutralization should be calculated on the server.
316          * @param {Boolean} [config.includeFitParameters]  Whether the parameters used in the neutralization curve fitting calculation
317          * should be included in the response.
318          * @param {String} [config.containerPath] The path to the study container containing the NAb summary,
319          *       if different than the current container. If not supplied, the current container's path will be used.
320          * @param {Function} config.success
321                 Function called when the "getStudyNabRuns" function executes successfully.
322                 This function will be called with the following arguments:
323                 <ul>
324                     <li>runs: an array of NAb run objects</li>
325                 </ul>
326         * @param {Function} [config.failure] Function called when execution of the "getStudyNabRuns" function fails.
327          *       This function will be called with the following arguments:
328  				<ul>
329  				    <li><b>errorInfo:</b> an object describing the error with the following fields:
330                          <ul>
331                              <li><b>exception:</b> the exception message</li>
332                              <li><b>exceptionClass:</b> the Java class of the exception thrown on the server</li>
333                              <li><b>stackTrace:</b> the Java stack trace at the point when the exception occurred</li>
334                          </ul>
335                      </li>
336                      <li><b>responseObj:</b> the XMLHttpResponseObject instance used to make the AJAX request</li>
337  				    <li><b>options:</b> the options used for the AJAX request</li>
338  				</ul>
339         * @param {Integer} [config.timeout] The maximum number of milliseconds to allow for this operation before
340         *       generating a timeout error (defaults to 30000).
341         */
342         getStudyNabRuns : function(config)
343         {
344             var dataObject = {};
345 
346             LABKEY.Utils.merge(dataObject, config);
347 
348             var successCallback = LABKEY.Utils.getOnSuccess(config);
349 
350             var requestConfig = {
351                 url : LABKEY.ActionURL.buildURL('nabassay', 'getStudyNabRuns', config.containerPath),
352                 method : 'GET',
353                 success: LABKEY.Utils.getCallbackWrapper(function(data, response){
354                     if(successCallback)
355                         successCallback.call(config.scope, data.runs);
356                 }, this),
357                 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config) || LABKEY.Utils.displayAjaxErrorResponse, config.scope, true),
358                 params : dataObject
359             };
360 
361             if (LABKEY.Utils.isDefined(config.timeout))
362                 requestConfig.timeout = config.timeout;
363 
364             LABKEY.Ajax.request(requestConfig);
365         },
366 
367         /**
368         * Retrieve the URL of an image that contains a graph of dilution curves for NAb results that have been copied to a study.
369          * Note that this method must be executed against the study folder containing the copied NAb summary data.
370          * @param {Object} config An object which contains the following configuration properties.
371          * @param {Array} config.objectIds The object Ids for the NAb data rows that have been copied to the study.
372          * This method will ignore requests to graph any object IDs that the current user does not have permission to view.
373          * @param {String} config.captionColumn The data column that should be used for per-specimen captions.  If the column
374          * doesn't exist, or if it has a null value, a sensible default will be chosen, generally specimen ID or participant/visit.
375          * @param {String} [config.chartTitle] The desired title for the chart. Defaults to no title.
376          * @param {String} [config.fitType] Allowable values are FIVE_PARAMETER, FOUR_PARAMETER, and POLYNOMIAL.
377          * Defaults to FIVE_PARAMETER.
378          * @param {String} [config.height] Desired height of the graph image in pixels. Defaults to 300.
379          * @param {String} [config.width] Desired width of the graph image in pixels. Defaults to 425.
380          * @param {String} [config.containerPath] The path to the study container containing the NAb summary data,
381          *       if different than the current container. If not supplied, the current container's path will be used.
382          * @param {Function} config.success
383                 Function called when the "getStudyNabGraphURL" function executes successfully.
384                 This function will be called with the following arguments:
385                 <ul>
386                     <li>result: an object with the following properties:
387                         <ul>
388                          <li>url: a string URL of the dilution curve graph.</li>
389                          <li>objectIds: an array containing the IDs of the samples that were successfully graphed.</li>
390                         </ul>
391                     </li>
392                     <li>responseObj: the XMLHttpResponseObject instance used to make the AJAX request</li>
393                     <li>options: the options used for the AJAX request</li>
394                 </ul>
395         * @param {Function} [config.failure] Function called when execution of the "getStudyNabGraphURL" function fails.
396          *       This function will be called with the following arguments:
397  				<ul>
398  				    <li><b>errorInfo:</b> an object describing the error with the following fields:
399                          <ul>
400                              <li><b>exception:</b> the exception message</li>
401                              <li><b>exceptionClass:</b> the Java class of the exception thrown on the server</li>
402                              <li><b>stackTrace:</b> the Java stack trace at the point when the exception occurred</li>
403                          </ul>
404                      </li>
405                      <li><b>responseObj:</b> the XMLHttpResponseObject instance used to make the AJAX request</li>
406  				    <li><b>options:</b> the options used for the AJAX request</li>
407  				</ul>
408         * @param {Integer} [config.timeout] The maximum number of milliseconds to allow for this operation before
409         *       generating a timeout error (defaults to 30000).
410         * @example Example:
411 <pre name="code" class="xml">
412 <script type="text/javascript">
413     function showGraph(data)
414     {
415         var el = document.getElementById("graphDiv");
416         if (data.objectIds && data.objectIds.length > 0)
417             el.innerHTML = '<img src=\"' + data.url + '\">';
418         else
419             el.innerHTML = 'No graph available.  Insufficient permissions, ' +
420                            'or no matching results were found.';
421     }
422 
423     function initiateGraph(ids)
424     {
425         LABKEY.Assay.getStudyNabGraphURL({
426             objectIds: ids,
427             success: showGraph,
428             captionColumn: 'VirusName',
429             chartTitle: 'My NAb Chart',
430             height: 500,
431             width: 700,
432             fitType: 'FOUR_PARAMETER'
433         });
434     }
435 
436     Ext.onReady(initiateGraph([185, 165]));
437 </script>
438 <div id="graphDiv">
439 </pre>
440 
441         */
442         getStudyNabGraphURL : function(config)
443         {
444             var parameters = {};
445 
446             LABKEY.Utils.applyTranslated(parameters, config, {objectIds: 'id'}, true, false);
447 
448             var requestConfig = {
449                 url : LABKEY.ActionURL.buildURL('nabassay', 'getStudyNabGraphURL', config.containerPath),
450                 method : 'GET',
451                 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope, false),
452                 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config) || LABKEY.Utils.displayAjaxErrorResponse, config.scope, true),
453                 params : parameters
454             };
455 
456             if(LABKEY.Utils.isDefined(config.timeout))
457                 requestConfig.timeout = config.timeout;
458 
459             LABKEY.Ajax.request(requestConfig);
460         }
461     };
462 };
463 
464 /** docs for methods defined in dom/Assay.js - primarily here to ensure API docs get generated with combined core/dom versions */
465 
466 /**
467  * Create an assay run and import results.
468  * @memberOf LABKEY.Assay
469  * @function
470  * @name importRun
471  * @param {Object} config An object which contains the following configuration properties.
472  * @param {Number} config.assayId The assay protocol id.
473  * @param {String} [config.containerPath] The path to the container in which the assay run will be imported,
474  *       if different than the current container. If not supplied, the current container's path will be used.
475  * @param {String} [config.name] The name of a run to create. If not provided, the run will be given the same name as the uploaded file or "[Untitled]".
476  * @param {String} [config.comment] Run comments.
477  * @param {Object} [config.properties] JSON formatted run properties.
478  * @param {Number} [config.batchId] The id of an existing {LABKEY.Exp.RunGroup} to add this run into.
479  * @param {Object} [config.batchProperties] JSON formatted batch properties.
480  * Only used if batchId is not provided when creating a new batch.
481  * @param {String} [config.runFilePath] Absolute or relative path to assay data file to be imported.
482  * The file must exist under the file or pipeline root of the container.  Only one of 'files', 'runFilePath', or 'dataRows' can be provided.
483  * @param {Array} [config.files] Array of <a href='https://developer.mozilla.org/en-US/docs/DOM/File'><code>File</code></a> objects
484  * or form file input elements to import.  Only one of 'files', 'runFilePath', or 'dataRows' can be provided.
485  * @param {Array} [config.dataRows] Array of assay results to import.  Only one of 'files', 'runFilePath', or 'dataRows' can be provided.
486  * @param {Function} config.success The success callback function will be called with the following arguments:
487  * <ul>
488  *     <li><b>json</b>: The success response object contains two properties:
489  *         <ul>
490  *             <li><b>success</b>: true</li>
491  *             <li><b>successurl</b>: The url to browse the newly imported assay run.</li>
492  *             <li><b>assayId</b>: The assay id.</li>
493  *             <li><b>batchId</b>: The previously existing or newly created batch id.</li>
494  *             <li><b>runId</b>: The newly created run id.</li>
495  *         </ul>
496  *     </li>
497  *     <li><b>response</b>: The XMLHttpResponseObject used to submit the request.</li>
498  * </ul>
499  * @param {Function} config.failure The error callback function will be called with the following arguments:
500  * <ul>
501  *     <li><b>errorInfo:</b> an object describing the error with the following fields:
502  *         <ul>
503  *             <li><b>exception:</b> the exception message</li>
504  *             <li><b>exceptionClass:</b> the Java class of the exception thrown on the server</li>
505  *             <li><b>stackTrace:</b> the Java stack trace at the point when the exception occurred</li>
506  *         </ul>
507  *     </li>
508  * <li><b>response:</b> the XMLHttpResponseObject used to submit the request.</li>
509  *
510  * @example Import a file that has been previously uploaded to the server:
511  *         LABKEY.Assay.importRun({
512      *             assayId: 3,
513      *             name: "new run",
514      *             runFilePath: "assaydata/2017-05-10/datafile.tsv",
515      *             success: function (json, response) {
516      *                 window.location = json.successurl;
517      *             },
518      *             failure: error (json, response) {
519      *             }
520      *         });
521  *
522  * @example Import JSON array of data rows:
523  *         LABKEY.Assay.importRun({
524      *             assayId: 3,
525      *             name: "new run",
526      *             dataRows: [{
527      *                  sampleId: "S-1",
528      *                  dataField: 100
529      *             },{
530      *                  sampleId: "S-2",
531      *                  dataField: 200
532      *             }]
533      *             success: function (json, response) {
534      *                 window.location = json.successurl;
535      *             },
536      *             failure: error (json, response) {
537      *             }
538      *         });
539  *
540  * @example Here is an example of retrieving one or more File objects from a form <code><input></code>
541  * element and submitting them together to create a new run.
542  * <input id='myfiles' type='file' multiple>
543  * <a href='#' onclick='doSubmit()'>Submit</a>
544  * <script>
545  *     function doSubmit() {
546      *         LABKEY.Assay.importRun({
547      *             assayId: 3,
548      *             name: "new run",
549      *             properties: {
550      *                 "Run Field": "value"
551      *             },
552      *             batchProperties: {
553      *                 "Batch Field": "value"
554      *             },
555      *             files: [ document.getElementById('myfiles') ],
556      *             success: function (json, response) {
557      *                 window.location = json.successurl;
558      *             },
559      *             failure: error (json, response) {
560      *             }
561      *         });
562      *     }
563  * </script>
564  *
565  * @example Alternatively, you may use an HTML form to submit the multipart/form-data without using the JavaScript API.
566  * <form action='./assay.importRun.api' method='POST' enctype='multipart/form-data'>
567  *     <input name='assayId' type='text' />
568  *     <input name='name' type='text' />
569  *     <input name='file' type='file' />
570  *     <input name='submit' type='submit' />
571  * </form>
572  */
573 
574 /**
575 * @name LABKEY.Assay.AssayDesign
576 * @class  Static class to describe the shape and fields of an assay.  Each of the {@link LABKEY.Assay}
577             'get' methods passes its success callback function an array of AssayDesigns.
578  *            <p>Additional Documentation:
579  *              <ul>
580  *                  <li><a href="https://www.labkey.org/Documentation/wiki-page.view?name=createDatasetViaAssay">LabKey Assays</a></li>
581  *              </ul>
582  *           </p>
583 */
584 
585 /**#@+
586 * @memberOf LABKEY.Assay.AssayDesign#
587 * @field
588 */
589 
590 /**
591 * @name LABKEY.Assay.AssayDesign#name
592 * @description   The name of the assay.
593 * @type String
594 */
595 
596 /**
597 * @name id
598 * @description The unique ID of the assay.
599 * @type Integer
600 */
601 
602 /**
603 * @name importController
604 * @description The name of the controller used for data import
605 * @type String
606 */
607 
608 /**
609 * @name importAction
610 * @description The name of the action used for data import
611 * @type String
612 */
613 
614 /**
615 * @name containerPath
616 * @description The path to the container in which this assay design is saved
617 * @type String
618 */
619 
620 /**
621 * @name type
622 * @description The name of the assay type.  Example:  "ELISpot"
623 * @type String
624 */
625 
626 /**
627 * @name projectLevel
628 * @description  Indicates whether this is a project-level assay.
629 * @type Boolean
630 */
631 
632 /**
633 * @name LABKEY.Assay.AssayDesign#description
634 * @description  Contains the assay description.
635 * @type String
636 */
637 
638 /**
639 * @name plateTemplate
640 * @description  Contains the plate template name if the assay is plate-based.  Undefined otherwise.
641 * @type String
642 */
643 
644 /**
645  * @name domainTypes
646  * @description An mapped enumeration of domain types to domain names. Useful when attempting to find a domain by type.
647  * The value is a domain name which can be used as a key lookup into the "domain" object.
648  * @type Object
649  */
650 
651 /**
652 * @name domains
653 * @description Map containing name/value pairs.  Typically contains three entries for three domains (batch, run and results).
654   * Each domain is associated with an array of objects that each describe a domain field.
655  *  Each field object has the following properties:
656   *        <ul>
657   *           <li><b>name: </b>The name of the domain field. (string)</li>
658   *           <li><b>typeName: </b> The name of the type of the domain field. (Human readable.) (string)</li>
659   *           <li><b>typeURI: </b> The URI that uniquely identifies the domain field type. (Not human readable.) (string)</li>
660   *           <li><b>label: </b> The domain field label. (string)</li>
661   *           <li><b>description: </b> The domain field description. (string)</li>
662   *           <li><b>formatString: </b> The format string applied to the domain field. (string)</li>
663   *           <li><b>required: </b> Indicates whether a value is required for this domain field. (boolean)</li>
664   *           <li><b>lookup.container: </b> If this domain field is a lookup, lookup.container holds the
665              String path to the lookup container or null if the lookup in the
666              same container.  Undefined otherwise.(string)</li>
667   *           <li><b>lookup.schema: </b> If this domain field object is a lookup, lookup.schema holds the
668             String name of the lookup schema.  Undefined otherwise.(string)</li>
669   *           <li><b>lookup.table: </b> If this domain field object is a lookup, lookup.table holds the String
670             name of the lookup query.  Undefined otherwise. (string)</li>
671   *           <li><b>lookup.keyColumn: </b> The primary key field in target table (string)</li>
672   *           <li><b>lookup.displayColumn: </b>The display column in target table (string)</li>
673   *       </ul>
674 * @type Object
675 */
676 
677 /**#@-*/
678 
679