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-2019 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 getDomainDetails(success, failure, parameters, containerPath) 64 { 65 LABKEY.Ajax.request({ 66 url : LABKEY.ActionURL.buildURL("property", "getDomainDetails.api", containerPath), 67 method : 'GET', 68 success: LABKEY.Utils.getCallbackWrapper(success), 69 failure: LABKEY.Utils.getCallbackWrapper(failure, this, true), 70 params : parameters 71 }); 72 } 73 74 function saveDomain(success, failure, parameters, containerPath) 75 { 76 LABKEY.Ajax.request({ 77 url : LABKEY.ActionURL.buildURL("property", "saveDomain.api", containerPath), 78 method : 'POST', 79 success: LABKEY.Utils.getCallbackWrapper(success), 80 failure: LABKEY.Utils.getCallbackWrapper(failure, this, true), 81 jsonData : parameters, 82 headers : { 83 'Content-Type' : 'application/json' 84 } 85 }); 86 } 87 88 function deleteDomain(success, failure, parameters, containerPath) 89 { 90 LABKEY.Ajax.request({ 91 url : LABKEY.ActionURL.buildURL("property", "deleteDomain.api", containerPath), 92 method : 'POST', 93 success: LABKEY.Utils.getCallbackWrapper(success), 94 failure: LABKEY.Utils.getCallbackWrapper(failure, this, true), 95 jsonData : parameters, 96 headers : { 97 'Content-Type' : 'application/json' 98 } 99 }); 100 } 101 102 function listDomains(success, failure, parameters, containerPath) 103 { 104 LABKEY.Ajax.request({ 105 url : LABKEY.ActionURL.buildURL("property", "listDomains.api", containerPath), 106 method : 'GET', 107 success: LABKEY.Utils.getCallbackWrapper(success), 108 failure: LABKEY.Utils.getCallbackWrapper(failure, this, true), 109 params : parameters 110 }); 111 } 112 113 /** @scope LABKEY.Domain */ 114 return { 115 116 /** 117 * Create a new domain with the given kind, domainDesign, and options or 118 * specify a <a href='https://www.labkey.org/Documentation/wiki-page.view?name=domainTemplates'>domain template</a> to use for the domain creation. 119 * Not all domain kinds can be created through this API. Currently supported domain kinds are: 120 * "IntList", "VarList", "SampleSet", "DataClass", "StudyDatasetDate", "StudyDatasetVisit", "Vocabulary". 121 * 122 * @param {Object} config An object which contains the following configuration properties. 123 * @param {Function} config.success Required success callback. 124 * @param {Function} [config.failure] Failure callback. 125 * @param {String} config.kind The domain kind to create. One of "IntList", "VarList", "SampleSet", or "DataClass". 126 * @param {String} config.domainName The name of the domain to create. 127 * @param {String} config.module The name of a module that contains the domain template group. 128 * @param {String} config.domainGroup The name of a domain template group. 129 * @param {String} config.domainTemplate The name of a domain template within the domain group. 130 * @param {Boolean} config.createDomain When using a domain template, create the domain. Defaults to true. 131 * @param {Boolean} config.importData When using a domain template, import initial data associated in the template. Defaults to true. 132 * @param {LABKEY.Domain.DomainDesign} config.domainDesign The domain design to save. 133 * @param {Object} [config.options] Arguments used to create the specific domain type. 134 * @param {String} [config.containerPath] The container path in which to create the domain. 135 * @example Create domain: 136 <pre name="code" class="xml"> 137 LABKEY.Domain.create({ 138 kind: "IntList", 139 domainDesign: { 140 name: "LookupCodes", 141 description: "integer key list", 142 fields: [{ 143 name: "id", rangeURI: "int" 144 },{ 145 name: "code", 146 rangeURI: "string", scale: 4 147 }] 148 }, 149 options: { 150 keyName: "id" 151 } 152 }); 153 </pre> 154 * @example Create domain from a <a href='https://www.labkey.org/Documentation/wiki-page.view?name=domainTemplates'>domain template</a>: 155 <pre name="code" class="xml"> 156 LABKEY.Domain.create({ 157 module: "mymodule", 158 domainGroup: "codes", 159 domainTemplate: "LookupCodes", 160 importData: false 161 }); 162 </pre> 163 * @example Import the initial data from the domain template of a previously created domain: 164 <pre name="code" class="xml"> 165 LABKEY.Domain.create({ 166 module: "mymodule", 167 domainGroup: "codes", 168 domainTemplate: "LookupCodes", 169 createDomain: false, 170 importData: true 171 }); 172 </pre> 173 */ 174 create : function (config) 175 { 176 // new-style 177 if (typeof config === "object") 178 { 179 createDomain(config.success, config.failure, config, config.containerPath); 180 } 181 // old-style 182 else if (arguments.length > 1) 183 { 184 var success = arguments[0], 185 failure = arguments[1], 186 params = {}, 187 containerPath; 188 189 if ((arguments.length == 4 || arguments.length == 5) && typeof arguments[3] === "string") 190 { 191 params.domainGroup = arguments[2]; 192 params.domainTemplate = arguments[3]; 193 containerPath = arguments[4]; 194 } 195 else 196 { 197 params.kind = arguments[2]; 198 params.domainDesign = arguments[3]; 199 params.options = arguments[4]; 200 containerPath = arguments[5]; 201 } 202 203 createDomain(success, failure, params, containerPath); 204 } 205 }, 206 207 /** 208 * This api is deprecated, use {@link LABKEY.Domain.getDomainDetails} instead. 209 * @param {Object} config An object which contains the following configuration properties. 210 * @param {Function} config.success Required. Function called if the 211 * "get" function executes successfully. Will be called with the argument {@link LABKEY.Domain.DomainDesign}, 212 * which describes the fields of a domain. 213 * @param {Function} [config.failure] Function called if execution of the "get" function fails. 214 * @param {String} config.schemaName Name of the schema 215 * @param {String} config.queryName Name of the query 216 * @param {String} config.domainId Id of the domain. This is an alternate way to identify the domain. 217 * SchemaName and queryName will be ignored if this value is not undefined or null. 218 * @param {String} [config.containerPath] The container path in which the requested Domain is defined. 219 * If not supplied, the current container path will be used. 220 * @example Example: 221 <pre name="code" class="xml"> 222 <script type="text/javascript"> 223 function successHandler(domainDesign) 224 { 225 var html = ''; 226 227 html += '<b>' + domainDesign.name + ':</b><br> '; 228 for (var i in domainDesign.fields) 229 { 230 html += ' ' + domainDesign.fields[i].name + '<br>'; 231 } 232 document.getElementById('testDiv').innerHTML = html; 233 } 234 235 function errorHandler(error) 236 { 237 alert('An error occurred retrieving data: ' + error); 238 } 239 240 LABKEY.Domain.get(successHandler, errorHandler, 'study', 'StudyProperties'); 241 </script> 242 <div id='testDiv'>Loading...</div> 243 </pre> 244 * @see LABKEY.Assay.AssayDesign 245 */ 246 get : function(config) 247 { 248 if (arguments.length > 1) 249 { 250 config = { 251 success: arguments[0], 252 failure: arguments[1], 253 schemaName: arguments[2], 254 queryName: arguments[3], 255 containerPath: arguments[4] 256 }; 257 } 258 259 getDomain( 260 config.success, 261 config.failure, 262 {schemaName: config.schemaName, queryName: config.queryName, domainId: config.domainId}, 263 config.containerPath); 264 }, 265 266 /** 267 * Gets a domain design along with domain kind specific properties. 268 * @param {Object} config An object which contains the following configuration properties. 269 * @param {Function} config.success Required. Function called if the 270 * "getDomainDetails" function executes successfully. Will be called with the argument {@link LABKEY.Domain.DomainDesign}, 271 * which describes the fields of a domain. 272 * @param {Function} [config.failure] Function called if execution of the "getDomainDetails" function fails. 273 * @param {String} config.schemaName Name of the schema 274 * @param {String} config.queryName Name of the query 275 * @param {String} config.domainId Id of the domain. This is an alternate way to identify the domain. 276 * SchemaName and queryName will be ignored if this value is not undefined or null. 277 * @param {String} [config.containerPath] The container path in which the requested Domain is defined. 278 * If not supplied, the current container path will be used. 279 * @example Example: 280 <pre name="code" class="xml"> 281 <script type="text/javascript"> 282 function successHandler(domainDesign) 283 { 284 var html = ''; 285 286 html += '<b>' + domainDesign.name + ':</b><br> '; 287 for (var i in domainDesign.fields) 288 { 289 html += ' ' + domainDesign.fields[i].name + '<br>'; 290 } 291 document.getElementById('testDiv').innerHTML = html; 292 } 293 294 function errorHandler(error) 295 { 296 alert('An error occurred retrieving data: ' + error); 297 } 298 299 LABKEY.Domain.getDomainDetails(successHandler, errorHandler, 'study', 'StudyProperties'); 300 </script> 301 <div id='testDiv'>Loading...</div> 302 </pre> 303 * @see LABKEY.Assay.AssayDesign 304 */ 305 getDomainDetails : function(config) 306 { 307 if (arguments.length > 1) 308 { 309 config = { 310 success: arguments[0], 311 failure: arguments[1], 312 schemaName: arguments[2], 313 queryName: arguments[3], 314 containerPath: arguments[4] 315 }; 316 } 317 318 getDomainDetails( 319 config.success, 320 config.failure, 321 {schemaName: config.schemaName, queryName: config.queryName, domainId: config.domainId}, 322 config.containerPath); 323 }, 324 325 /** 326 * Lists all the domains within a given container. Specify domain kinds to get the targeted list of domain kinds. 327 * @param {Object} config An object which contains the following configuration properties. 328 * @param {Function} config.success Required success callback. 329 * @param {Function} [config.failure] Failure callback. 330 * @param {Boolean} config.includeFields Include Fields of in the list of domains. Defaults to false. 331 * @param {Boolean} config.includeProjectAndShared Includes domains in projects and shared. Defaults to false. 332 * @param {Array} config.domainKinds The list of domain Kinds to include in the list. Defaults to all the domains in container. 333 * @param {String} config.containerPath Container path of the domains holding container. 334 * @example List domains: 335 <pre name="code" class="xml"> 336 LABKEY.Domain.listDomains({ 337 includeFields: "true", 338 domainKinds: ["ExtensibleTable", "Vocabulary"] 339 }); 340 </pre> 341 */ 342 listDomains : function(config) 343 { 344 var params = { 345 includeFields: config.includeFields, 346 includeProjectAndShared: config.includeProjectAndShared 347 }; 348 349 if (config.domainKinds) 350 params.domainKinds = config.domainKinds; 351 352 listDomains( 353 config.success, 354 config.failure, 355 params, 356 config.containerPath); 357 }, 358 359 /** 360 * Saves the provided domain design. 361 * Note: All of the domain properties are expected to be present before saving, and not just the diff - the easiest way 362 * is to get the existing domain via {@Link LABKEY.Domain.getDomainDetails} and update the resultant json with your changes before saving. 363 * @param {Object} config An object which contains the following configuration properties. 364 * @param {Function} config.success Required. Function called if this 365 function executes successfully. No parameters will be passed to the success callback. 366 * @param {Function} [config.failure] Function called if execution of this function fails. 367 * @param {LABKEY.Domain.DomainDesign} config.domainDesign The domain design to save. 368 * @param {String} config.schemaName Name of the schema 369 * @param {String} config.queryName Name of the query 370 * @param {String} config.domainId Id of the domain. This is an alternate way to identify the domain to update. 371 * SchemaName and queryName will be ignored if this value is not undefined or null. 372 * @param {String} [config.containerPath] The container path in which the requested Domain is defined. 373 * If not supplied, the current container path will be used. 374 * @param {boolean} config.includeWarnings set this to true, if server side warnings are desired along with the errors 375 * If this is set to true and there are warnings detected, they will prevent the save from completing successfully 376 * @param {Object} [config.options] Domain Kind specific properties. 377 * If not supplied, will be ignored. 378 * Note: Certain domain kind specific properties are read-only and cannot be updated. 379 * Read-only properties for 'IntList' & 'VarList' domain kinds: listId, domainId, keyName, keyType, and lastIndexed. 380 */ 381 save : function(config) 382 { 383 if (arguments.length > 1) 384 { 385 config = { 386 success: arguments[0], 387 failure: arguments[1], 388 domainDesign: arguments[2], 389 schemaName: arguments[3], 390 queryName: arguments[4], 391 containerPath: arguments[5], 392 includeWarnings: arguments[6], 393 options: arguments[7] 394 }; 395 } 396 397 saveDomain( 398 config.success, 399 config.failure, 400 {domainDesign: config.domainDesign, schemaName: config.schemaName, queryName: config.queryName, 401 domainId: config.domainId, includeWarnings: config.includeWarnings, options: config.options}, 402 config.containerPath); 403 }, 404 405 /** 406 * Delete a domain. 407 * 408 * @param config 409 * @param {Object} config An object which contains the following configuration properties. 410 * @param {Function} config.success. 411 * @param {Function} [config.failure] 412 * @param {String} config.schemaName Name of the schema 413 * @param {String} config.queryName Name of the query 414 * @param {String} [config.containerPath] The container path in which the requested Domain is defined. 415 * If not supplied, the current container path will be used. 416 */ 417 drop : function (config) 418 { 419 deleteDomain( 420 config.success, 421 config.failure, 422 {domainDesign: config.domainDesign, schemaName: config.schemaName, queryName: config.queryName}, 423 config.containerPath); 424 }, 425 426 /** 427 * Get property descriptor information. 428 * @param {Object} config An object which contains the following configuration properties. 429 * @param {Function} [config.success] Success callback is a function that is called with an array of property information in the same format as 'fields' within {@link LABKEY.Domain.DomainDesign}. 430 * @param {Function} [config.failure] Failure callback. 431 * @param {Array} config.propertyIds Array of integer propertyIds. 432 * @param {Array} config.propertyURIs Array of string propertyURIs. 433 * @param {String} config.containerPath Container path of the property definitions. 434 */ 435 getProperties : function (config) 436 { 437 var parameters = {}; 438 if (config.propertyIds) 439 parameters.propertyIds = config.propertyIds; 440 441 if (config.propertyURIs) 442 parameters.propertyURIs = config.propertyURIs; 443 444 LABKEY.Ajax.request({ 445 url: LABKEY.ActionURL.buildURL("property", "getProperties.api", config.containerPath, parameters), 446 success: LABKEY.Utils.getCallbackWrapper(config.success), 447 failure: LABKEY.Utils.getCallbackWrapper(config.failure, this, true) 448 }); 449 } 450 }; 451 452 453 }; 454 455 /** 456 * @name LABKEY.Domain.DomainDesign 457 * @class DomainDesign static class to describe the shape and fields of a domain. The {@link LABKEY.Domain} 458 * 'getDomainDetails' and 'save' methods employ DomainDesign. 459 */ 460 461 /**#@+ 462 * @memberOf LABKEY.Domain.DomainDesign# 463 * @field 464 */ 465 466 /** 467 * @name name 468 * @description The name of this domain. 469 * @type String 470 */ 471 472 /** 473 * @name domainId 474 * @description The unique ID of this domain. 475 * @type Integer 476 */ 477 478 /** 479 * @name description 480 * @description The description of this domain. 481 * @type String 482 */ 483 484 /** 485 * @name domainURI 486 * @description The URI of this domain. 487 * @type String 488 */ 489 490 /** 491 * @name fields 492 * @description An array of objects that each describe a domain field. Each object has the following properties: 493 * (Note: Not all properties below are expected to have values or will have values. See {@Link LABKEY.Domain} 'Create' to see minimally required properties when creating a Domain.) 494 * <ul> 495 * <li><b>propertyId:</b> The unique ID of this field. (integer)</li> 496 * <li><b>propertyURI:</b> The URI of this field. (string)</li> 497 * <li><b>ontologyURI:</b> The URI of the ontology this field belongs to. (string)</li> 498 * <li><b>name:</b> The name of this field. (string)</li> 499 * <li><b>description:</b> The description of this field (may be blank). (string)</li> 500 * <li><b>rangeURI:</b> The URI for this field's range definition. (string)</li> 501 * <li><b>conceptURI:</b> The URI of this field's concept. (string)</li> 502 * <li><b>label:</b> The friendly label for this field. (string)</li> 503 * <li><b>searchTerms:</b> The search terms for this field. (string)</li> 504 * <li><b>semanticType:</b> The semantic type of this field. (string)</li> 505 * <li><b>format:</b> The format string defined for this field. (string)</li> 506 * <li><b>required:</b> Indicates whether this field is required to have a value (i.e. cannot be null). (boolean)</li> 507 * <li><b>lookupContainer:</b> If this domain field is a lookup, this holds the container in which to look. (string)</li> 508 * <li><b>lookupSchema:</b> If this domain field is a lookup, this holds the schema in which to look. (string)</li> 509 * <li><b>lookupQuery:</b> if this domain field is a lookup, this holds the query in which to look. (string)</li> 510 * <li><b>defaultDisplayValue:</b> Default value to display. (string)</li> 511 * <li><b>defaultValue:</b> Default value for the field. (string)</li> 512 * <li><b>defaultValueType:</b> Default value type for the field. (string)</li> 513 * <li><b>hidden:</b> Indicates whether this field is to be hidden or shown in a view. (boolean)</li> 514 * <li><b>isPrimaryKey:</b> Indicates whether this field is a Primary Key. (boolean)</li> 515 * <li><b>lockType:</b> Set lock level on this field. Expected value should be one of: "NotLocked" 516 * (can change all properties, this is default) or "PartiallyLocked" (can't change name and type property) or "FullyLocked" (can't change any of the properties). (string)</li> 517 * <li><b>phi:</b> Set PHI level on this field. Expected value should be one of: "NotPhi" (default) or "Limited" or "PHI" or "Restricted". (string)</li> 518 * <li><b>scale:</b> Scale for the field. (int)</li> 519 * <li><b>shownInDetailsView:</b> Indicates whether this field is to be shown in Details view. (boolean)</li> 520 * <li><b>shownInInsertView:</b> Indicates whether this field is to be shown in an Insert view. (boolean)</li> 521 * <li><b>shownInUpdateView:</b> Indicates whether this field is to be shown in an Update view. (boolean)</li> 522 * <li><b>url:</b> A url associated with this field. (string)</li> 523 * </ul> 524 * @type Object 525 */ 526 527 /** 528 * @name indices 529 * @description An array of objects that each designate an index upon the domain. Each object has the following properties: 530 * <ul> 531 * <li><b>columnNames:</b> An array of strings, where each string is the name of a domain field that will be an index. (array)</li> 532 * <li><b>unique:</b> Indicates whether the domain field is allowed to contain any duplicate values. (boolean)</li> 533 * </ul> 534 * @type Object 535 */ 536 537 /**#@-*/ 538