UNPKG

d2

Version:

Javascript library for DHIS2

203 lines (176 loc) 6.68 kB
import { isValidUid, isArray, checkType } from '../lib/check' import { throwError } from '../lib/utils' import Model from './Model' import ModelDefinition from './ModelDefinition' import Pager from '../pager/Pager' function throwIfContainsOtherThanModelObjects(values) { if (values && values[Symbol.iterator]) { const toCheck = [...values] toCheck.forEach(value => { if (!(value instanceof Model)) { throwError( 'Values of a ModelCollection must be instances of Model' ) } }) } } function throwIfContainsModelWithoutUid(values) { if (values && values[Symbol.iterator]) { const toCheck = [...values] toCheck.forEach(value => { if (!isValidUid(value.id)) { throwError( 'Can not add a Model without id to a ModelCollection' ) } }) } } /** * Collection of `Model` objects that can be interacted upon. Can contain a pager object to easily navigate * pages within the system. * * @memberof module:model */ class ModelCollection { /** * @constructor * * @param {ModelDefinition} modelDefinition The `ModelDefinition` that this collection is for. This defines the type of models that * are allowed to be added to the collection. * @param {Model[]} values Initial values that should be added to the collection. * @param {Object} pagerData Object with pager data. This object contains data that will be put into the `Pager` instance. * * @description * * Creates a new `ModelCollection` object based on the passed `modelDefinition`. Additionally values can be added by passing * `Model` objects in the `values` parameter. The collection also exposes a pager object which can be used to navigate through * the pages in the collection. For more information see the `Pager` class. */ constructor(modelDefinition, values, pagerData) { checkType(modelDefinition, ModelDefinition) /** * @property {ModelDefinition} modelDefinition The `ModelDefinition` that this collection is for. This defines the type of models that * are allowed to be added to the collection. */ this.modelDefinition = modelDefinition /** * @property {Pager} pager Pager object that is created from the pagerData that was passed when the collection was constructed. If no pager data was present * the pager will have default values. */ this.pager = new Pager(pagerData, modelDefinition) // We can not extend the Map object right away in v8 contexts. this.valuesContainerMap = new Map() this[Symbol.iterator] = this.valuesContainerMap[Symbol.iterator].bind( this.valuesContainerMap ) throwIfContainsOtherThanModelObjects(values) throwIfContainsModelWithoutUid(values) // Add the values separately as not all Iterators return the same values if (isArray(values)) { values.forEach(value => this.valuesContainerMap.set(value.id, value) ) } } /** * @property {Number} size The number of Model objects that are in the collection. * * @description * Contains the number of Model objects that are in this collection. If the collection is a collection with a pager. This * does not take into account all the items in the database. Therefore when a pager is present on the collection * the size will return the items on that page. To get the total number of items consult the pager. */ get size() { return this.valuesContainerMap.size } /** * Adds a Model instance to the collection. The model is checked if it is a correct instance of `Model` and if it has * a valid id. A valid id is a uid string of 11 alphanumeric characters. * * @param {Model} value Model instance to add to the collection. * @returns {ModelCollection} Returns itself for chaining purposes. * * @throws {Error} When the passed value is not an instance of `Model` * @throws {Error} Throws error when the passed value does not have a valid id. */ add(value) { throwIfContainsOtherThanModelObjects([value]) throwIfContainsModelWithoutUid([value]) this.set(value.id, value) return this } /** * If working with the Map type object is inconvenient this method can be used to return the values * of the collection as an Array object. * * @returns {Array} Returns the values of the collection as an array. */ toArray() { const resultArray = [] this.forEach(model => { resultArray.push(model) }) return resultArray } static create(modelDefinition, values, pagerData) { return new ModelCollection(modelDefinition, values, pagerData) } static throwIfContainsOtherThanModelObjects(value) { return throwIfContainsOtherThanModelObjects(value) } static throwIfContainsModelWithoutUid(value) { return throwIfContainsModelWithoutUid(value) } /** * Clear the collection and remove all it's values. * * @returns {this} Returns itself for chaining purposes; */ // TODO: Reset the pager? clear() { return this.valuesContainerMap.clear.call(this.valuesContainerMap) } delete(...args) { return this.valuesContainerMap.delete.call( this.valuesContainerMap, ...args ) } entries() { return this.valuesContainerMap.entries.call(this.valuesContainerMap) } // FIXME: This calls the forEach function with the values Map and not with the ModelCollection as the third argument forEach(...args) { return this.valuesContainerMap.forEach.call( this.valuesContainerMap, ...args ) } get(...args) { return this.valuesContainerMap.get.call( this.valuesContainerMap, ...args ) } has(...args) { return this.valuesContainerMap.has.call( this.valuesContainerMap, ...args ) } keys() { return this.valuesContainerMap.keys.call(this.valuesContainerMap) } set(...args) { return this.valuesContainerMap.set.call( this.valuesContainerMap, ...args ) } values() { return this.valuesContainerMap.values.call(this.valuesContainerMap) } } export default ModelCollection