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 Domain static class to retrieve and edit domain definitions.
 22  *
 23  *        <p>A domain is a collection of fields.  Each data type (e.g., Assays, Lists, Datasets, Sample Sets and
 24  *        Custom Protein Lists) provides specialized handling for the domains it
 25  *        defines.   The number of domains defined by a data type varies; for example, Assays
 26  *        define multiple domains (batch, run, etc.), while Lists
 27  *        and Datasets define only one domain each.</p>
 28  *
 29  *            <p>Additional Documentation:
 30  *              <ul>
 31  *                  <li><a href="https://www.labkey.org/Documentation/wiki-page.view?name=propertyFields">LabKey Dataset Domain Fields</a></li>
 32  *              </ul>
 33  *           </p>
 34 */
 35 LABKEY.Domain = new function()
 36 {
 37 
 38     function createDomain(success, failure, parameters, containerPath)
 39     {
 40         LABKEY.Ajax.request({
 41             url : LABKEY.ActionURL.buildURL("property", "createDomain.api", containerPath),
 42             method : 'POST',
 43             success: LABKEY.Utils.getCallbackWrapper(success),
 44             failure: LABKEY.Utils.getCallbackWrapper(failure, this, true),
 45             jsonData : parameters,
 46             headers : {
 47                 'Content-Type' : 'application/json'
 48             }
 49         });
 50     }
 51 
 52     function getDomain(success, failure, parameters, containerPath)
 53     {
 54         LABKEY.Ajax.request({
 55             url : LABKEY.ActionURL.buildURL("property", "getDomain.api", containerPath),
 56             method : 'GET',
 57             success: LABKEY.Utils.getCallbackWrapper(success),
 58             failure: LABKEY.Utils.getCallbackWrapper(failure, this, true),
 59             params : parameters
 60         });
 61     }
 62 
 63     function saveDomain(success, failure, parameters, containerPath)
 64     {
 65         LABKEY.Ajax.request({
 66             url : LABKEY.ActionURL.buildURL("property", "saveDomain.api", containerPath),
 67             method : 'POST',
 68             success: LABKEY.Utils.getCallbackWrapper(success),
 69             failure: LABKEY.Utils.getCallbackWrapper(failure, this, true),
 70             jsonData : parameters,
 71             headers : {
 72                 'Content-Type' : 'application/json'
 73             }
 74         });
 75     }
 76 
 77     function deleteDomain(success, failure, parameters, containerPath)
 78     {
 79         LABKEY.Ajax.request({
 80             url : LABKEY.ActionURL.buildURL("property", "deleteDomain.api", containerPath),
 81             method : 'POST',
 82             success: LABKEY.Utils.getCallbackWrapper(success),
 83             failure: LABKEY.Utils.getCallbackWrapper(failure, this, true),
 84             jsonData : parameters,
 85             headers : {
 86                 'Content-Type' : 'application/json'
 87             }
 88         });
 89     }
 90 
 91     /** @scope LABKEY.Domain */
 92     return {
 93 
 94         /**
 95          * Create a new domain with the given kind, domainDesign, and options or
 96          * specify a <a href='https://www.labkey.org/Documentation/wiki-page.view?name=domainTemplates'>domain template</a> to use for the domain creation.
 97          * Not all domain kinds can be created through this API.  Currently supported domain kinds are:
 98          * "IntList", "VarList", "SampleSet", "DataClass", "StudyDatasetDate", "StudyDatasetVisit".
 99          *
100          * @param {Object} config An object which contains the following configuration properties.
101          * @param {Function} config.success Required success callback.
102          * @param {Function} [config.failure] Failure callback.
103          * @param {String} config.kind The domain kind to create. One of "IntList", "VarList", "SampleSet", or "DataClass".
104          * @param {String} config.domainName The name of the domain to create.
105          * @param {String} config.module The name of a module that contains the domain template group.
106          * @param {String} config.domainGroup The name of a domain template group.
107          * @param {String} config.domainTemplate The name of a domain template within the domain group.
108          * @param {Boolean} config.createDomain When using a domain template, create the domain.  Defaults to true.
109          * @param {Boolean} config.importData When using a domain template, import initial data associated in the template.  Defaults to true.
110          * @param {LABKEY.Domain.DomainDesign} config.domainDesign The domain design to save.
111          * @param {Object} [config.options] Arguments used to create the specific domain type.
112          * @param {String} [config.containerPath] The container path in which to create the domain.
113          * @example Create domain:
114 <pre name="code" class="xml">
115 LABKEY.Domain.create({
116   kind: "IntList",
117   domainDesign: {
118     name: "LookupCodes",
119     description: "integer key list",
120     fields: [{
121       name: "id", rangeURI: "int"
122     },{
123       name: "code",
124       rangeURI: "string", scale: 4
125     }]
126   },
127   options: {
128     keyName: "id"
129   }
130 });
131 </pre>
132          * @example Create domain from a <a href='https://www.labkey.org/Documentation/wiki-page.view?name=domainTemplates'>domain template</a>:
133 <pre name="code" class="xml">
134 LABKEY.Domain.create({
135   module: "mymodule",
136   domainGroup: "codes",
137   domainTemplate: "LookupCodes",
138   importData: false
139 });
140          </pre>
141          * @example Import the initial data from the domain template of a previously created domain:
142 <pre name="code" class="xml">
143 LABKEY.Domain.create({
144   module: "mymodule",
145   domainGroup: "codes",
146   domainTemplate: "LookupCodes",
147   createDomain: false,
148   importData: true
149 });
150 </pre>
151          */
152         create : function (config)
153         {
154             // new-style
155             if (typeof config === "object")
156             {
157                 createDomain(config.success, config.failure, config, config.containerPath);
158             }
159             // old-style
160             else if (arguments.length > 1)
161             {
162                 var success = arguments[0],
163                     failure = arguments[1],
164                     params = {},
165                     containerPath;
166 
167                 if ((arguments.length == 4 || arguments.length == 5) && typeof arguments[3] === "string")
168                 {
169                     params.domainGroup = arguments[2];
170                     params.domainTemplate = arguments[3];
171                     containerPath = arguments[4];
172                 }
173                 else
174                 {
175                     params.kind = arguments[2];
176                     params.domainDesign = arguments[3];
177                     params.options = arguments[4];
178                     containerPath = arguments[5];
179                 }
180 
181                 createDomain(success, failure, params, containerPath);
182             }
183         },
184 
185 	/**
186 	* Gets a domain design.
187      * @param {Object} config An object which contains the following configuration properties.
188 	* @param {Function} config.success Required. Function called if the
189 	*	"get" function executes successfully. Will be called with the argument {@link LABKEY.Domain.DomainDesign},
190     *    which describes the fields of a domain.
191 	* @param {Function} [config.failure] Function called if execution of the "get" function fails.
192 	* @param {String} config.schemaName Name of the schema
193 	* @param {String} config.queryName Name of the query
194 	* @param {String} [config.containerPath] The container path in which the requested Domain is defined.
195 	*       If not supplied, the current container path will be used.
196 	* @example Example:
197 <pre name="code" class="xml">
198 <script type="text/javascript">
199 	function successHandler(domainDesign)
200 	{
201 		var html = '';
202 
203 		html += '<b>' + domainDesign.name + ':</b><br> ';
204 		for (var i in domainDesign.fields)
205 		{
206 			html += '   ' + domainDesign.fields[i].name + '<br>';
207 		}
208 		document.getElementById('testDiv').innerHTML = html;
209 	}
210 
211 	function errorHandler(error)
212 	{
213 		alert('An error occurred retrieving data: ' + error);
214 	}
215 
216 	LABKEY.Domain.get(successHandler, errorHandler, 'study', 'StudyProperties');
217 </script>
218 <div id='testDiv'>Loading...</div>
219 </pre>
220 	  * @see LABKEY.Assay.AssayDesign
221 	  */
222         get : function(config)
223         {
224             if (arguments.length > 1)
225             {
226                 config = {
227                     success: arguments[0],
228                     failure: arguments[1],
229                     schemaName: arguments[2],
230                     queryName: arguments[3],
231                     containerPath: arguments[4]
232                 };
233             }
234 
235             getDomain(
236                 config.success,
237                 config.failure,
238                 {schemaName: config.schemaName, queryName: config.queryName},
239                 config.containerPath);
240         },
241 
242         /**
243          * Saves the provided domain design
244          * @param {Object} config An object which contains the following configuration properties.
245          * @param {Function} config.success Required. Function called if this
246                   function executes successfully. No parameters will be passed to the success callback.
247          * @param {Function} [config.failure] Function called if execution of this function fails.
248          * @param {LABKEY.Domain.DomainDesign} config.domainDesign The domain design to save.
249          * @param {String} config.schemaName Name of the schema
250          * @param {String} config.queryName Name of the query
251          * @param {String} [config.containerPath] The container path in which the requested Domain is defined.
252          *       If not supplied, the current container path will be used.
253          */
254         save : function(config)
255         {
256             if (arguments.length > 1)
257             {
258                 config = {
259                     success: arguments[0],
260                     failure: arguments[1],
261                     domainDesign: arguments[2],
262                     schemaName: arguments[3],
263                     queryName: arguments[4],
264                     containerPath: arguments[5]
265                 };
266             }
267 
268             saveDomain(
269                 config.success,
270                 config.failure,
271                 {domainDesign: config.domainDesign, schemaName: config.schemaName, queryName: config.queryName},
272                 config.containerPath);
273         },
274 
275         /**
276          * Delete a domain.
277          *
278          * @param config
279          * @param {Object} config An object which contains the following configuration properties.
280          * @param {Function} config.success.
281          * @param {Function} [config.failure]
282          * @param {String} config.schemaName Name of the schema
283          * @param {String} config.queryName Name of the query
284          * @param {String} [config.containerPath] The container path in which the requested Domain is defined.
285          *       If not supplied, the current container path will be used.
286          */
287         drop : function (config)
288         {
289             deleteDomain(
290                 config.success,
291                 config.failure,
292                 {domainDesign: config.domainDesign, schemaName: config.schemaName, queryName: config.queryName},
293                 config.containerPath);
294         }
295     };
296 
297 
298 };
299 
300 /**
301 * @name LABKEY.Domain.DomainDesign
302 * @class  DomainDesign static class to describe the shape and fields of a domain.  The {@link LABKEY.Domain}
303 *             'get' and 'set' methods employ DomainDesign.
304 */
305 
306 /**#@+
307 * @memberOf LABKEY.Domain.DomainDesign#
308 * @field
309 */
310 
311 /**
312 * @name name
313 * @description   The name of this domain.
314 * @type String
315 */
316 
317 /**
318 * @name domainId
319 * @description The uinque ID of this domain.
320 * @type Integer
321 */
322 
323 /**
324 * @name description
325 * @description  The description of this domain.
326 * @type String
327 */
328 
329 /**
330 * @name domainURI
331 * @description  The URI of this domain.
332 * @type String
333 */
334 
335 /**
336 * @name fields
337 * @description An array of objects that each describe a domain field.  Each object has the following properties:
338     *      <ul>
339     *          <li><b>propertyId:</b> The unique ID of this field. (integer)</li>
340     *          <li><b>propertyURI:</b> The URI of this field. (string)</li>
341     *          <li><b>ontologyURI:</b> The URI of the ontology this field belongs to. (string)</li>
342     *          <li><b>name:</b> The name of this field. (string)</li>
343     *          <li><b>description:</b> The description of this field (may be blank). (string)</li>
344     *          <li><b>rangeURI:</b> The URI for this field's range definition. (string)</li>
345     *          <li><b>conceptURI:</b> The URI of this field's concept. (string)</li>
346     *          <li><b>label:</b> The friendly label for this field. (string)</li>
347     *          <li><b>searchTerms:</b> The search terms for this field. (string)</li>
348     *          <li><b>semanticType:</b> The semantic type of this field. (string)</li>
349     *          <li><b>format:</b> The format string defined for this field. (string)</li>
350     *          <li><b>required:</b> Indicates whether this field is required to have a value (i.e. cannot be null). (boolean)</li>
351     *          <li><b>lookupContainer:</b> If this domain field is a lookup, this holds the container in which to look. (string)</li>
352     *          <li><b>lookupSchema:</b> If this domain field is a lookup, this holds the schema in which to look. (string)</li>
353     *          <li><b>lookupQuery:</b> if this domain field is a lookup, this holds the query in which to look. (string)</li>
354     *      </ul>
355     * @type Object
356 */
357 
358 /**#@-*/
359