d2
Version:
Javascript library for DHIS2
625 lines (532 loc) • 44 kB
HTML
<html lang="en">
<head>
<meta charset="utf-8">
<title>model/ModelDefinition.js - Documentation</title>
<script src="scripts/prettify/prettify.js"></script>
<script src="scripts/prettify/lang-css.js"></script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<input type="checkbox" id="nav-trigger" class="nav-trigger" />
<label for="nav-trigger" class="navicon-button x">
<div class="navicon"></div>
</label>
<label for="nav-trigger" class="overlay"></label>
<nav >
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="GeoFeatures.html">GeoFeatures</a></li><li></li><li><a href="module-analytics.Analytics.html">Analytics</a><ul class='methods'><li data-type='method'><a href="module-analytics.Analytics.html#.getAnalytics">getAnalytics</a></li></ul></li><li><a href="module-analytics.AnalyticsAggregate.html">AnalyticsAggregate</a><ul class='methods'><li data-type='method'><a href="module-analytics.AnalyticsAggregate.html#get">get</a></li><li data-type='method'><a href="module-analytics.AnalyticsAggregate.html#getDataValueSet">getDataValueSet</a></li><li data-type='method'><a href="module-analytics.AnalyticsAggregate.html#getDebugSql">getDebugSql</a></li><li data-type='method'><a href="module-analytics.AnalyticsAggregate.html#getRawData">getRawData</a></li></ul></li><li><a href="module-analytics.AnalyticsEvents.html">AnalyticsEvents</a><ul class='methods'><li data-type='method'><a href="module-analytics.AnalyticsEvents.html#get">get</a></li><li data-type='method'><a href="module-analytics.AnalyticsEvents.html#getAggregate">getAggregate</a></li><li data-type='method'><a href="module-analytics.AnalyticsEvents.html#getCluster">getCluster</a></li><li data-type='method'><a href="module-analytics.AnalyticsEvents.html#getCount">getCount</a></li><li data-type='method'><a href="module-analytics.AnalyticsEvents.html#getQuery">getQuery</a></li></ul></li><li><a href="module-analytics.AnalyticsRequest.html">AnalyticsRequest</a><ul class='methods'><li data-type='method'><a href="module-analytics.AnalyticsRequest.html#fromModel">fromModel</a></li></ul></li><li><a href="module-api.Api.html">Api</a><ul class='methods'><li data-type='method'><a href="module-api.Api.html#get">get</a></li><li data-type='method'><a href="module-api.Api.html#patch">patch</a></li><li data-type='method'><a href="module-api.Api.html#post">post</a></li><li data-type='method'><a href="module-api.Api.html#setBaseUrl">setBaseUrl</a></li><li data-type='method'><a href="module-api.Api.html#setDefaultHeaders">setDefaultHeaders</a></li><li data-type='method'><a href="module-api.Api.html#setUnauthorizedCallback">setUnauthorizedCallback</a></li><li data-type='method'><a href="module-api.Api.html#update">update</a></li></ul></li><li><a href="module-current-user.CurrentUser.html">CurrentUser</a><ul class='methods'><li data-type='method'><a href="module-current-user.CurrentUser.html#.create">create</a></li><li data-type='method'><a href="module-current-user.CurrentUser.html#canCreate">canCreate</a></li><li data-type='method'><a href="module-current-user.CurrentUser.html#canCreatePrivate">canCreatePrivate</a></li><li data-type='method'><a href="module-current-user.CurrentUser.html#canCreatePublic">canCreatePublic</a></li><li data-type='method'><a href="module-current-user.CurrentUser.html#canDelete">canDelete</a></li><li data-type='method'><a href="module-current-user.CurrentUser.html#canUpdate">canUpdate</a></li><li data-type='method'><a href="module-current-user.CurrentUser.html#getDataViewOrganisationUnits">getDataViewOrganisationUnits</a></li><li data-type='method'><a href="module-current-user.CurrentUser.html#getOrganisationUnits">getOrganisationUnits</a></li><li data-type='method'><a href="module-current-user.CurrentUser.html#getUserGroupIds">getUserGroupIds</a></li><li data-type='method'><a href="module-current-user.CurrentUser.html#getUserGroups">getUserGroups</a></li><li data-type='method'><a href="module-current-user.CurrentUser.html#getUserRoles">getUserRoles</a></li></ul></li><li><a href="module-current-user.UserAuthorities.html">UserAuthorities</a><ul class='methods'><li data-type='method'><a href="module-current-user.UserAuthorities.html#.create">create</a></li><li data-type='method'><a href="module-current-user.UserAuthorities.html#has">has</a></li></ul></li><li><a href="module-current-user.UserDataStore.html">UserDataStore</a><ul class='methods'><li data-type='method'><a href="module-current-user.UserDataStore.html#.getUserDataStore">getUserDataStore</a></li><li data-type='method'><a href="module-current-user.UserDataStore.html#create">create</a></li><li data-type='method'><a href="module-current-user.UserDataStore.html#delete">delete</a></li><li data-type='method'><a href="module-current-user.UserDataStore.html#get">get</a></li><li data-type='method'><a href="module-current-user.UserDataStore.html#getAll">getAll</a></li><li data-type='method'><a href="module-current-user.UserDataStore.html#has">has</a></li></ul></li><li><a href="module-current-user.UserDataStoreNamespace.html">UserDataStoreNamespace</a><ul class='methods'><li data-type='method'><a href="module-current-user.UserDataStoreNamespace.html#delete">delete</a></li><li data-type='method'><a href="module-current-user.UserDataStoreNamespace.html#get">get</a></li><li data-type='method'><a href="module-current-user.UserDataStoreNamespace.html#getKeys">getKeys</a></li><li data-type='method'><a href="module-current-user.UserDataStoreNamespace.html#set">set</a></li><li data-type='method'><a href="module-current-user.UserDataStoreNamespace.html#update">update</a></li></ul></li><li><a href="module-current-user.UserSettings.html">UserSettings</a><ul class='methods'><li data-type='method'><a href="module-current-user.UserSettings.html#all">all</a></li><li data-type='method'><a href="module-current-user.UserSettings.html#get">get</a></li><li data-type='method'><a href="module-current-user.UserSettings.html#set">set</a></li></ul></li><li><a href="module-datastore.DataStore.html">DataStore</a><ul class='methods'><li data-type='method'><a href="module-datastore.DataStore.html#.getDataStore">getDataStore</a></li><li data-type='method'><a href="module-datastore.DataStore.html#create">create</a></li><li data-type='method'><a href="module-datastore.DataStore.html#delete">delete</a></li><li data-type='method'><a href="module-datastore.DataStore.html#get">get</a></li><li data-type='method'><a href="module-datastore.DataStore.html#getAll">getAll</a></li><li data-type='method'><a href="module-datastore.DataStore.html#has">has</a></li></ul></li><li><a href="module-datastore.DataStoreNamespace.html">DataStoreNamespace</a><ul class='methods'><li data-type='method'><a href="module-datastore.DataStoreNamespace.html#delete">delete</a></li><li data-type='method'><a href="module-datastore.DataStoreNamespace.html#get">get</a></li><li data-type='method'><a href="module-datastore.DataStoreNamespace.html#getKeys">getKeys</a></li><li data-type='method'><a href="module-datastore.DataStoreNamespace.html#getMetaData">getMetaData</a></li><li data-type='method'><a href="module-datastore.DataStoreNamespace.html#set">set</a></li><li data-type='method'><a href="module-datastore.DataStoreNamespace.html#update">update</a></li></ul></li><li><a href="module-i18n-I18n.html">I18n</a><ul class='methods'><li data-type='method'><a href="module-i18n-I18n.html#.getI18n">getI18n</a></li><li data-type='method'><a href="module-i18n-I18n.html#addSource">addSource</a></li><li data-type='method'><a href="module-i18n-I18n.html#addStrings">addStrings</a></li><li data-type='method'><a href="module-i18n-I18n.html#getTranslation">getTranslation</a></li><li data-type='method'><a href="module-i18n-I18n.html#getUntranslatedStrings">getUntranslatedStrings</a></li><li data-type='method'><a href="module-i18n-I18n.html#isTranslated">isTranslated</a></li><li data-type='method'><a href="module-i18n-I18n.html#load">load</a></li></ul></li><li><a href="module-model.Filter.html">Filter</a><ul class='methods'><li data-type='method'><a href="module-model.Filter.html#.getFilter">getFilter</a></li><li data-type='method'><a href="module-model.Filter.html#equals">equals</a></li><li data-type='method'><a href="module-model.Filter.html#ilike">ilike</a></li><li data-type='method'><a href="module-model.Filter.html#in">in</a></li><li data-type='method'><a href="module-model.Filter.html#like">like</a></li><li data-type='method'><a href="module-model.Filter.html#notEqual">notEqual</a></li><li data-type='method'><a href="module-model.Filter.html#notIn">notIn</a></li><li data-type='method'><a href="module-model.Filter.html#nToken">nToken</a></li><li data-type='method'><a href="module-model.Filter.html#on">on</a></li><li data-type='method'><a href="module-model.Filter.html#operator">operator</a></li><li data-type='method'><a href="module-model.Filter.html#token">token</a></li></ul></li><li><a href="module-model.Filters.html">Filters</a><ul class='methods'><li data-type='method'><a href="module-model.Filters.html#.getFilters">getFilters</a></li><li data-type='method'><a href="module-model.Filters.html#getFilterList">getFilterList</a></li><li data-type='method'><a href="module-model.Filters.html#getFilters">getFilters</a></li><li data-type='method'><a href="module-model.Filters.html#getQueryFilterValues">getQueryFilterValues</a></li><li data-type='method'><a href="module-model.Filters.html#list">list</a></li><li data-type='method'><a href="module-model.Filters.html#logicMode">logicMode</a></li><li data-type='method'><a href="module-model.Filters.html#on">on</a></li></ul></li><li><a href="module-model.Model.html">Model</a><ul class='methods'><li data-type='method'><a href="module-model.Model.html#.create">create</a></li></ul></li><li><a href="module-model.ModelBase.html">ModelBase</a><ul class='methods'><li data-type='method'><a href="module-model.ModelBase.html#create">create</a></li><li data-type='method'><a href="module-model.ModelBase.html#delete">delete</a></li><li data-type='method'><a href="module-model.ModelBase.html#getCollectionChildren">getCollectionChildren</a></li><li data-type='method'><a href="module-model.ModelBase.html#getCollectionChildrenPropertyNames">getCollectionChildrenPropertyNames</a></li><li data-type='method'><a href="module-model.ModelBase.html#getDirtyChildren">getDirtyChildren</a></li><li data-type='method'><a href="module-model.ModelBase.html#getDirtyPropertyNames">getDirtyPropertyNames</a></li><li data-type='method'><a href="module-model.ModelBase.html#getEmbeddedObjectCollectionPropertyNames">getEmbeddedObjectCollectionPropertyNames</a></li><li data-type='method'><a href="module-model.ModelBase.html#getReferenceProperties">getReferenceProperties</a></li><li data-type='method'><a href="module-model.ModelBase.html#hasDirtyChildren">hasDirtyChildren</a></li><li data-type='method'><a href="module-model.ModelBase.html#isDirty">isDirty</a></li><li data-type='method'><a href="module-model.ModelBase.html#resetDirtyState">resetDirtyState</a></li><li data-type='method'><a href="module-model.ModelBase.html#save">save</a></li><li data-type='method'><a href="module-model.ModelBase.html#toJSON">toJSON</a></li><li data-type='method'><a href="module-model.ModelBase.html#validate">validate</a></li></ul></li><li><a href="module-model.ModelCollection.html">ModelCollection</a><ul class='methods'><li data-type='method'><a href="module-model.ModelCollection.html#add">add</a></li><li data-type='method'><a href="module-model.ModelCollection.html#clear">clear</a></li><li data-type='method'><a href="module-model.ModelCollection.html#toArray">toArray</a></li></ul></li><li><a href="module-model.ModelCollectionProperty.html">ModelCollectionProperty</a><ul class='methods'><li data-type='method'><a href="module-model.ModelCollectionProperty.html#.create">create</a></li><li data-type='method'><a href="module-model.ModelCollectionProperty.html#add">add</a></li><li data-type='method'><a href="module-model.ModelCollectionProperty.html#isDirty">isDirty</a></li><li data-type='method'><a href="module-model.ModelCollectionProperty.html#remove">remove</a></li><li data-type='method'><a href="module-model.ModelCollectionProperty.html#resetDirtyState">resetDirtyState</a></li><li data-type='method'><a href="module-model.ModelCollectionProperty.html#save">save</a></li><li data-type='method'><a href="module-model.ModelCollectionProperty.html#updateDirty">updateDirty</a></li></ul></li><li><a href="module-model.ModelDefinition.html">ModelDefinition</a><ul class='methods'><li data-type='method'><a href="module-model.ModelDefinition.html#.createFromSchema">createFromSchema</a></li><li data-type='method'><a href="module-model.ModelDefinition.html#create">create</a></li><li data-type='method'><a href="module-model.ModelDefinition.html#delete">delete</a></li><li data-type='method'><a href="module-model.ModelDefinition.html#get">get</a></li><li data-type='method'><a href="module-model.ModelDefinition.html#getOwnedPropertyNames">getOwnedPropertyNames</a></li><li data-type='method'><a href="module-model.ModelDefinition.html#getTranslatableProperties">getTranslatableProperties</a></li><li data-type='method'><a href="module-model.ModelDefinition.html#getTranslatablePropertiesWithKeys">getTranslatablePropertiesWithKeys</a></li><li data-type='method'><a href="module-model.ModelDefinition.html#isTranslatable">isTranslatable</a></li><li data-type='method'><a href="module-model.ModelDefinition.html#list">list</a></li><li data-type='method'><a href="module-model.ModelDefinition.html#save">save</a></li></ul></li><li><a href="module-model.ModelDefinitions.html">ModelDefinitions</a><ul class='methods'><li data-type='method'><a href="module-model.ModelDefinitions.html#add">add</a></li><li data-type='method'><a href="module-model.ModelDefinitions.html#mapThroughDefinitions">mapThroughDefinitions</a></li></ul></li><li><a href="module-model.ModelValidation.html">ModelValidation</a><ul class='methods'><li data-type='method'><a href="module-model.ModelValidation.html#.getModelValidation">getModelValidation</a></li><li data-type='method'><a href="module-model.ModelValidation.html#validate">validate</a></li><li data-type='method'><a href="module-model.ModelValidation.html#validateAgainstSchema">validateAgainstSchema</a></li></ul></li><li><a href="module-model.Pager.html">Pager</a><ul class='methods'><li data-type='method'><a href="module-model.Pager.html#getNextPage">getNextPage</a></li><li data-type='method'><a href="module-model.Pager.html#getPreviousPage">getPreviousPage</a></li><li data-type='method'><a href="module-model.Pager.html#goToPage">goToPage</a></li><li data-type='method'><a href="module-model.Pager.html#hasNextPage">hasNextPage</a></li><li data-type='method'><a href="module-model.Pager.html#hasPreviousPage">hasPreviousPage</a></li></ul></li><li><a href="module-system.System.html">System</a><ul class='methods'><li data-type='method'><a href="module-system.System.html#.compareVersions">compareVersions</a></li><li data-type='method'><a href="module-system.System.html#.getSystem">getSystem</a></li><li data-type='method'><a href="module-system.System.html#.isVersionCompatible">isVersionCompatible</a></li><li data-type='method'><a href="module-system.System.html#.parseVersionString">parseVersionString</a></li><li data-type='method'><a href="module-system.System.html#installAppVersion">installAppVersion</a></li><li data-type='method'><a href="module-system.System.html#loadAppStore">loadAppStore</a></li><li data-type='method'><a href="module-system.System.html#loadInstalledApps">loadInstalledApps</a></li><li data-type='method'><a href="module-system.System.html#reloadApps">reloadApps</a></li><li data-type='method'><a href="module-system.System.html#setInstalledApps">setInstalledApps</a></li><li data-type='method'><a href="module-system.System.html#setSystemInfo">setSystemInfo</a></li><li data-type='method'><a href="module-system.System.html#uninstallApp">uninstallApp</a></li><li data-type='method'><a href="module-system.System.html#uploadApp">uploadApp</a></li></ul></li><li><a href="module-system.SystemConfiguration.html">SystemConfiguration</a><ul class='methods'><li data-type='method'><a href="module-system.SystemConfiguration.html#all">all</a></li><li data-type='method'><a href="module-system.SystemConfiguration.html#get">get</a></li></ul></li><li><a href="module-system.SystemSettings.html">SystemSettings</a><ul class='methods'><li data-type='method'><a href="module-system.SystemSettings.html#all">all</a></li><li data-type='method'><a href="module-system.SystemSettings.html#get">get</a></li></ul></li></ul><h3>Modules</h3><ul><li><a href="module-analytics.html">analytics</a></li><li><a href="module-api.html">api</a></li><li><a href="module-current-user.html">current-user</a></li><li><a href="module-d2.html">d2</a><ul class='members'><li data-type='member'><a href="module-d2.html#.config">config</a></li></ul><ul class='methods'><li data-type='method'><a href="module-d2.html#.getInstance">getInstance</a></li><li data-type='method'><a href="module-d2.html#.getManifest">getManifest</a></li><li data-type='method'><a href="module-d2.html#.init">init</a></li><li data-type='method'><a href="module-d2.html#~getUserSettings">getUserSettings</a></li></ul></li><li><a href="module-datastore.html">datastore</a></li><li><a href="module-i18n.html">i18n</a></li><li><a href="module-lib_check.html">lib/check</a><ul class='methods'><li data-type='method'><a href="module-lib_check.html#.checkDefined">checkDefined</a></li><li data-type='method'><a href="module-lib_check.html#.isValidUid">isValidUid</a></li></ul></li><li><a href="module-lib_utils.html">lib/utils</a><ul class='methods'><li data-type='method'><a href="module-lib_utils.html#.customEncodeURIComponent">customEncodeURIComponent</a></li><li data-type='method'><a href="module-lib_utils.html#.pick">pick</a></li></ul></li><li><a href="module-model.html">model</a></li><li><a href="module-period_generators.html">period/generators</a><ul class='methods'><li data-type='method'><a href="module-period_generators.html#.createPeriodGeneratorsForLocale">createPeriodGeneratorsForLocale</a></li></ul></li><li><a href="module-system.html">system</a></li><li><a href="module-uid.html">uid</a><ul class='methods'><li data-type='method'><a href="module-uid.html#.generateUid">generateUid</a></li><li data-type='method'><a href="module-uid.html#.isValidUid">isValidUid</a></li></ul></li></ul><h3>Namespaces</h3><ul><li><a href="module-d2.init-d2.html">d2</a></li></ul><h3>Tutorials</h3><ul><li><a href="tutorial-FAQ.html">FAQ</a></li><li><a href="tutorial-overview.html">overview</a></li></ul><h3>Global</h3><ul><li><a href="global.html#addDataDimension">addDataDimension</a></li><li><a href="global.html#addDataFilter">addDataFilter</a></li><li><a href="global.html#addDimension">addDimension</a></li><li><a href="global.html#addFilter">addFilter</a></li><li><a href="global.html#addOrgUnitDimension">addOrgUnitDimension</a></li><li><a href="global.html#addOrgUnitFilter">addOrgUnitFilter</a></li><li><a href="global.html#addPeriodDimension">addPeriodDimension</a></li><li><a href="global.html#addPeriodFilter">addPeriodFilter</a></li><li><a href="global.html#byOrgUnit">byOrgUnit</a></li><li><a href="global.html#computeWeekBasedPeriod">computeWeekBasedPeriod</a></li><li><a href="global.html#getAll">getAll</a></li><li><a href="global.html">getGeoFeatures</a></li><li><a href="global.html">isValidDisplayName</a></li><li><a href="global.html">isValidOrgUnit</a></li><li><a href="global.html">isValidOrgUnitGroup</a></li><li><a href="global.html">isValidOrgUnitLevel</a></li><li><a href="global.html">isValidUserOrgUnit</a></li><li><a href="global.html#withAggregateData">withAggregateData</a></li><li><a href="global.html#withAggregationType">withAggregationType</a></li><li><a href="global.html#withApprovalLevel">withApprovalLevel</a></li><li><a href="global.html#withAsc">withAsc</a></li><li><a href="global.html#withBbox">withBbox</a></li><li><a href="global.html#withClusterSize">withClusterSize</a></li><li><a href="global.html#withCollapseDataDimensions">withCollapseDataDimensions</a></li><li><a href="global.html#withColumns">withColumns</a></li><li><a href="global.html#withCoordinateField">withCoordinateField</a></li><li><a href="global.html#withCoordinatesOnly">withCoordinatesOnly</a></li><li><a href="global.html#withDesc">withDesc</a></li><li><a href="global.html#withDisplayProperty">withDisplayProperty</a></li><li><a href="global.html#withEndDate">withEndDate</a></li><li><a href="global.html#withEventStatus">withEventStatus</a></li><li><a href="global.html#withFormat">withFormat</a></li><li><a href="global.html#withHideEmptyColumns">withHideEmptyColumns</a></li><li><a href="global.html#withHideEmptyRows">withHideEmptyRows</a></li><li><a href="global.html#withHierarchyMeta">withHierarchyMeta</a></li><li><a href="global.html#withIgnoreLimit">withIgnoreLimit</a></li><li><a href="global.html#withIncludeClusterPoints">withIncludeClusterPoints</a></li><li><a href="global.html#withIncludeMetadataDetails">withIncludeMetadataDetails</a></li><li><a href="global.html#withIncludeNumDen">withIncludeNumDen</a></li><li><a href="global.html#withInputIdScheme">withInputIdScheme</a></li><li><a href="global.html#withLimit">withLimit</a></li><li><a href="global.html#withMeasureCriteria">withMeasureCriteria</a></li><li><a href="global.html#withOuMode">withOuMode</a></li><li><a href="global.html#withOutputIdScheme">withOutputIdScheme</a></li><li><a href="global.html#withOutputType">withOutputType</a></li><li><a href="global.html#withPage">withPage</a></li><li><a href="global.html#withPageSize">withPageSize</a></li><li><a href="global.html#withParameters">withParameters</a></li><li><a href="global.html#withPath">withPath</a></li><li><a href="global.html#withPreAggregationMeasureCriteria">withPreAggregationMeasureCriteria</a></li><li><a href="global.html#withProgram">withProgram</a></li><li><a href="global.html#withProgramStatus">withProgramStatus</a></li><li><a href="global.html#withRelativePeriodDate">withRelativePeriodDate</a></li><li><a href="global.html#withRows">withRows</a></li><li><a href="global.html#withShowHierarchy">withShowHierarchy</a></li><li><a href="global.html#withSkipData">withSkipData</a></li><li><a href="global.html#withSkipMeta">withSkipMeta</a></li><li><a href="global.html#withSkipRounding">withSkipRounding</a></li><li><a href="global.html#withSortOrder">withSortOrder</a></li><li><a href="global.html#withStage">withStage</a></li><li><a href="global.html#withStartDate">withStartDate</a></li><li><a href="global.html#withTableLayout">withTableLayout</a></li><li><a href="global.html#withUserOrgUnit">withUserOrgUnit</a></li><li><a href="global.html#withValue">withValue</a></li></ul>
</nav>
<div id="main">
<h1 class="page-title">model/ModelDefinition.js</h1>
<section>
<article>
<pre class="prettyprint source linenums"><code>import { checkType, isObject, checkDefined, isDefined } from '../lib/check'
import {
addLockedProperty,
curry,
copyOwnProperties,
updateAPIUrlWithBaseUrlVersionNumber,
pick,
} from '../lib/utils'
import ModelDefinitions from './ModelDefinitions'
import Model from './Model'
import ModelCollection from './ModelCollection'
import ModelCollectionProperty from './ModelCollectionProperty'
import schemaTypes from '../lib/SchemaTypes'
import Filters from './Filters'
import { DIRTY_PROPERTY_LIST } from './ModelBase'
import { getDefaultValuesForModelType } from './config'
import { getOwnedPropertyJSON } from './helpers/json'
function createModelPropertyDescriptor(propertiesObject, schemaProperty) {
const propertyName = schemaProperty.collection
? schemaProperty.collectionName
: schemaProperty.name
const propertyDetails = {
// Actual property descriptor properties
configurable: false,
enumerable: true,
get() {
return this.dataValues[propertyName]
},
}
// Store available constants for ENUM type properties
if (schemaProperty.constants) {
propertyDetails.constants = schemaProperty.constants
}
// Only add a setter for writable properties
if (schemaProperty.writable) {
propertyDetails.set = function dynamicPropertySetter(value) {
// TODO: Objects and Arrays are considered unequal when their data is the same and therefore trigger a dirty
if (
(!isObject(value) && value !== this.dataValues[propertyName]) ||
isObject(value)
) {
this.dirty = true
this[DIRTY_PROPERTY_LIST].add(propertyName)
this.dataValues[propertyName] = value
}
}
}
if (propertyName) {
propertiesObject[propertyName] = propertyDetails
}
}
function createPropertiesObject(schemaProperties) {
const propertiesObject = {}
const createModelPropertyDescriptorOn = curry(
createModelPropertyDescriptor,
propertiesObject
)
;(schemaProperties || []).forEach(createModelPropertyDescriptorOn)
return propertiesObject
}
// eslint-disable-next-line complexity
function createValidationSetting(validationObject, schemaProperty) {
const propertyName = schemaProperty.collection
? schemaProperty.collectionName
: schemaProperty.name
const validationDetails = {
persisted: schemaProperty.persisted,
type: schemaTypes.typeLookup(schemaProperty.propertyType),
required: schemaProperty.required,
min: schemaProperty.min,
max: schemaProperty.max,
owner: schemaProperty.owner,
unique: schemaProperty.unique,
writable: schemaProperty.writable,
ordered: Boolean(schemaProperty.ordered),
embeddedObject: Boolean(schemaProperty.embeddedObject),
}
function getReferenceTypeFrom(property) {
if (property.href) {
return property.href.split('/').pop()
}
return undefined
}
// Add a referenceType to be able to get a hold of the reference objects model.
if (
validationDetails.type === 'REFERENCE' ||
(validationDetails.type === 'COLLECTION' &&
schemaProperty.itemPropertyType === 'REFERENCE')
) {
validationDetails.referenceType = getReferenceTypeFrom(schemaProperty)
}
if (propertyName) {
validationObject[propertyName] = validationDetails
}
}
function createValidations(schemaProperties) {
const validationsObject = {}
const createModelPropertyOn = curry(
createValidationSetting,
validationsObject
)
;(schemaProperties || []).forEach(createModelPropertyOn)
return validationsObject
}
function shouldBeModelCollectionProperty(model, models) {
// eslint-disable-next-line complexity
return function shouldBeModelCollectionPropertyIterator(modelProperty) {
return (
model &&
models &&
model.modelDefinition &&
model.modelDefinition.modelValidations &&
model.modelDefinition.modelValidations[modelProperty] &&
model.modelDefinition.modelValidations[modelProperty].type ===
'COLLECTION' &&
models.hasOwnProperty(
model.modelDefinition.modelValidations[modelProperty]
.referenceType
)
)
}
}
function isAnUpdate(modelToCheck) {
return Boolean(modelToCheck.id)
}
const translatableProperties = new WeakMap()
/**
* Definition of a Model. Basically this object contains the meta data related to the Model. Like `name`, `apiEndPoint`, `modelValidation`, etc.
* It also has methods to create and load Models that are based on this definition. The Data element `ModelDefinition` would be used to create Data Element `Model`s
*
* Note: ModelDefinition has a property `api` that is used for the communication with the dhis2 api. The value of this
* property is an instance of `Api`.
*
* @memberof module:model
*/
class ModelDefinition {
// eslint-disable-next-line complexity
constructor(schema = {}, properties, validations, attributes, authorities) {
checkType(schema.singular, 'string')
checkType(schema.plural, 'string', 'Plural')
addLockedProperty(this, 'name', schema.singular)
addLockedProperty(this, 'displayName', schema.displayName)
addLockedProperty(this, 'plural', schema.plural)
addLockedProperty(this, 'isShareable', schema.shareable || false)
addLockedProperty(this, 'isMetaData', schema.metadata || false)
addLockedProperty(this, 'apiEndpoint', schema.apiEndpoint)
addLockedProperty(this, 'javaClass', schema.klass)
addLockedProperty(
this,
'identifiableObject',
schema && schema.identifiableObject
)
addLockedProperty(this, 'modelProperties', properties)
addLockedProperty(this, 'modelValidations', validations)
addLockedProperty(this, 'attributeProperties', attributes)
addLockedProperty(this, 'authorities', authorities)
addLockedProperty(this, 'translatable', schema.translatable || false)
this.filters = Filters.getFilters(this)
translatableProperties.set(
this,
(schema.properties || [])
.filter(prop => prop.translationKey)
.map(({ name, translationKey }) => ({ name, translationKey }))
)
// TODO: The function getOwnedPropertyJSON should probably not be exposed, perhaps we could have a getJSONForModel(ownedPropertiesOnly=true) method.
this.getOwnedPropertyJSON = getOwnedPropertyJSON.bind(this)
}
filter() {
return this.clone().filters
}
/**
* Creates a fresh Model instance based on the `ModelDefinition`. If data is passed into the method that
* data will be loaded into the matching properties of the model.
*
* @param {Object} [data] Data values that should be loaded into the model.
*
* @returns {Model} Returns the newly created model instance.
*
* @example
* dataElement.create({name: 'ANC', id: 'd2sf33s3ssf'});
*/
create(data) {
const model = Model.create(this)
const models = ModelDefinitions.getModelDefinitions()
const dataValues = data
? Object.assign({}, data)
: getDefaultValuesForModelType(model.modelDefinition.name)
Object.keys(model)
.filter(shouldBeModelCollectionProperty(model, models))
.forEach(modelProperty => {
const {
referenceType,
} = model.modelDefinition.modelValidations[modelProperty]
let values = []
if (Array.isArray(dataValues[modelProperty])) {
values = dataValues[modelProperty].map(value =>
models[referenceType].create(value)
)
} else if (
dataValues[modelProperty] === true ||
dataValues[modelProperty] === undefined
) {
values = dataValues[modelProperty]
}
dataValues[modelProperty] = ModelCollectionProperty.create(
model,
models[referenceType],
modelProperty,
values
)
model.dataValues[modelProperty] = dataValues[modelProperty]
})
Object.keys(model)
.filter(
modelProperty =>
!shouldBeModelCollectionProperty(
model,
models
)(modelProperty)
)
.forEach(modelProperty => {
model.dataValues[modelProperty] = dataValues[modelProperty]
})
return model
}
clone() {
const ModelDefinitionPrototype = Object.getPrototypeOf(this)
const priorFilters = this.filters.getFilterList()
const clonedDefinition = copyOwnProperties(
Object.create(ModelDefinitionPrototype),
this
)
clonedDefinition.filters = Filters.getFilters(
clonedDefinition,
priorFilters
)
return clonedDefinition
}
/**
* Get a `Model` instance from the api loaded with data that relates to `identifier`.
* This will do an API call and return a Promise that resolves with a `Model` or rejects with the api error message.
*
* @param {String} identifier
* @param {Object} [queryParams={fields: ':all'}] Query parameters that should be passed to the GET query.
* @returns {Promise} Resolves with a `Model` instance or an error message.
*
* @example
* //Do a get request for the dataElement with given id (d2sf33s3ssf) and print it's name
* //when that request is complete and the model is loaded.
* dataElement.get('d2sf33s3ssf')
* .then(model => console.log(model.name));
*/
get(
identifier,
queryParams = {
fields: ':all,attributeValues[:all,attribute[id,name,displayName]]',
}
) {
checkDefined(identifier, 'Identifier')
if (Array.isArray(identifier)) {
return this.list({ filter: [`id:in:[${identifier.join(',')}]`] })
}
// TODO: should throw error if API has not been defined
return this.api
.get([this.apiEndpoint, identifier].join('/'), queryParams)
.then(data => this.create(data))
.catch(response => {
if (response.message) {
return Promise.reject(response.message)
}
return Promise.reject(response)
})
}
/**
* Loads a list of models.
*
* @param {Object} [listParams={fields: ':all'}] Query parameters that should be passed to the GET query.
* @returns {Promise} ModelCollection collection of models objects of the `ModelDefinition` type.
*
* @example
* // Loads a list of models and prints their name.
* dataElement.list()
* .then(modelCollection => {
* modelCollection.forEach(model => console.log(model.name));
* });
*/
list(listParams = {}) {
const { apiEndpoint, ...extraParams } = listParams
const definedRootJunction = this.filters.rootJunction
? { rootJunction: this.filters.rootJunction }
: {}
const params = Object.assign(
{ fields: ':all' },
definedRootJunction,
extraParams
)
const definedFilters = this.filters.getQueryFilterValues()
if (!isDefined(params.filter)) {
delete params.filter
if (definedFilters.length) {
params.filter = definedFilters
}
}
// If listParams.apiEndpoint exists, send the request there in stead of this.apiEndpoint
return this.api
.get(apiEndpoint || this.apiEndpoint, params)
.then(responseData =>
ModelCollection.create(
this,
responseData[this.plural].map(data => this.create(data)),
Object.assign(responseData.pager || {}, { query: params })
)
)
}
/**
* This method is used by the `Model` instances to save the model when calling `model.save()`.
*
* @param {Model} model The model that should be saved to the server.
* @returns {Promise} A promise which resolves when the save was successful
* or rejects when it failed. The promise will resolve with the data that is
* returned from the server.
*
* @note {warning} This should generally not be called directly.
*/
// TODO: check the return status of the save to see if it was actually successful and not ignored
save(model) {
if (isAnUpdate(model)) {
const jsonPayload = getOwnedPropertyJSON.bind(this)(model)
// Fallback to modelDefinition if href is unavailable
const updateUrl = model.dataValues.href
? updateAPIUrlWithBaseUrlVersionNumber(
model.dataValues.href,
this.api.baseUrl
)
: [model.modelDefinition.apiEndpoint, model.dataValues.id].join(
'/'
)
// Save the existing model
return this.api.update(updateUrl, jsonPayload, true)
}
return this.saveNew(model)
}
saveNew(model) {
const jsonPayload = getOwnedPropertyJSON.bind(this)(model)
// Its a new object
return this.api.post(this.apiEndpoint, jsonPayload)
}
/**
* This method returns a list of property names that that are defined
* as "owner" properties on this schema. This means these properties are used
* when saving the model to the server.
*
* @returns {String[]} Returns an array of property names.
*
* @example
* dataElement.getOwnedPropertyNames()
*/
getOwnedPropertyNames() {
return Object.keys(this.modelValidations).filter(
propertyName => this.modelValidations[propertyName].owner
)
}
/**
* This method is used by the `Model` instances to delete the model when calling `model.delete()`.
*
* @returns {Promise} Returns a promise to the deletion operation
*
* @note {warning} This should generally not be called directly.
*/
delete(model) {
if (model.dataValues.href) {
return this.api.delete(model.dataValues.href)
}
return this.api.delete(
[model.modelDefinition.apiEndpoint, model.dataValues.id].join('/')
)
}
/**
* Check for if the Model supports translations
*
* @returns {Boolean} True when the schema can be translated, false otherwise
*/
isTranslatable() {
return this.translatable
}
/**
* These properties can be translated using the DHIS2 _database_ translations.
*
* @returns {String[]} Returns a list of property names on the object that are translatable.
*/
getTranslatableProperties() {
return translatableProperties.get(this).map(pick('name'))
}
/**
* This method is similar to getTranslatableProperties() but in addition to the property names also returns the
* `translationKey` that is used to save the translations for the property names.
*
* @returns {Object[]} Returns an array with objects that have `name` and `translationKey` properties.
*/
getTranslatablePropertiesWithKeys() {
return translatableProperties.get(this)
}
/**
* @static
*
* This method creates a new `ModelDefinition` based on a JSON structure called
* a schema. A schema represents the structure of a domain model as it is
* required by DHIS. Since these schemas can not be altered on the server from
* the modelDefinition is frozen to prevent accidental changes to the definition.
*
* @param {Object} schema A schema definition received from the web api (/api/schemas)
* @param {Object[]} attributes A list of attribute objects that describe custom attributes (/api/attributes)
*
* @returns {ModelDefinition} Frozen model definition object.
*
* @example
* ModelDefinition.createFromSchema(schemaDefinition, attributes);
*
* @note {info} An example of a schema definition can be found on
* https://apps.dhis2.org/demo/api/schemas/dataElement
*/
static createFromSchema(schema, attributes = []) {
let ModelDefinitionClass
checkType(schema, Object, 'Schema')
if (
typeof ModelDefinition.specialClasses[schema.singular] ===
'function'
) {
ModelDefinitionClass =
ModelDefinition.specialClasses[schema.singular]
} else {
ModelDefinitionClass = ModelDefinition
}
return Object.freeze(
new ModelDefinitionClass(
schema,
Object.freeze(createPropertiesObject(schema.properties)),
Object.freeze(createValidations(schema.properties)),
attributes.reduce((current, attributeDefinition) => {
current[attributeDefinition.name] = attributeDefinition
return current
}, {}),
schema.authorities
)
)
}
}
class UserModelDefinition extends ModelDefinition {
// TODO: userCredentials should always be included, no matter what the query params, that is currently not the case
get(identifier, queryParams = { fields: ':all,userCredentials[:owner]' }) {
return super.get(identifier, queryParams)
}
}
class DataSetModelDefinition extends ModelDefinition {
create(data = {}) {
const hasData = Boolean(Object.keys(data).length)
// Filter out the compulsoryDataElementOperands structure from the retrieved data
// This structure does not follow the convention of a typical reference. We can not create a proper
// ModelCollection for this collection.
const dataClone = Object.keys(data)
.filter(key => key !== 'compulsoryDataElementOperands')
.reduce((obj, key) => {
obj[key] = data[key]
return obj
}, {})
// Create the model using the usual way of creating a model
// Only pass data when there is data in the object passed to the constructor. This will guarantee
// that the empty ModelCollections are created properly.
const model = super.create(hasData ? dataClone : undefined)
// Set the compulsoryDataElementOperands onto the dataValues so it will be included during the save operations
model.dataValues.compulsoryDataElementOperands =
data.compulsoryDataElementOperands
return model
}
}
class OrganisationUnitModelDefinition extends ModelDefinition {
// If a 'root' is specified when listing organisation units the results will be limited to the root and its
// descendants. This is special behavior for the organisation unit API endpoint, which is documented here:
// https://dhis2.github.io/dhis2-docs/master/en/developer/html/webapi_organisation_units.html
list(extraParams = {}) {
const { root, ...params } = extraParams
if (extraParams.hasOwnProperty('root') && root) {
params.apiEndpoint = `${this.apiEndpoint}/${root}`
}
return super.list(params)
}
}
ModelDefinition.specialClasses = {
user: UserModelDefinition,
dataSet: DataSetModelDefinition,
organisationUnit: OrganisationUnitModelDefinition,
}
export default ModelDefinition
</code></pre>
</article>
</section>
</div>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.6.6</a> on Thu Nov 18 2021 08:51:53 GMT+0000 (Coordinated Universal Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
</footer>
<script>prettyPrint();</script>
<script src="scripts/linenumber.js"></script>
</body>
</html>