UNPKG

@inversifyjs/core

Version:

InversifyJs core package

156 lines 6.22 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.OneToManyMapStar = void 0; const NOT_FOUND_INDEX = -1; /** * Data structure able to efficiently manage a set of models related to a set of properties in a one to many relation. */ class OneToManyMapStar { #modelToRelationMap; #relationToModelsMaps; #spec; constructor(spec) { this.#modelToRelationMap = new Map(); this.#relationToModelsMaps = {}; for (const specProperty of Reflect.ownKeys(spec)) { this.#relationToModelsMaps[specProperty] = new Map(); } this.#spec = spec; } add(model, relation) { this.#buildOrGetModelArray(model).push(relation); for (const relationKey of Reflect.ownKeys(relation)) { this.#buildOrGetRelationModels(relationKey, relation[relationKey]).push(model); } } clone() { const modelToCloneModelMap = this.#buildModelToCloneModelMap(); const relationToCloneRelationMap = this.#buildRelationToRelationModelMap(); const properties = Reflect.ownKeys(this.#spec); const clone = this._buildNewInstance(this.#spec); this.#pushRelationEntriesIntoRelationMap(this.#modelToRelationMap, clone.#modelToRelationMap, modelToCloneModelMap, relationToCloneRelationMap); for (const property of properties) { this.#pushModelEntriesIntoModelMap(this.#relationToModelsMaps[property], clone.#relationToModelsMaps[property], modelToCloneModelMap); } return clone; } get(key, value) { return this.#relationToModelsMaps[key].get(value); } getAllKeys(key) { return this.#relationToModelsMaps[key].keys(); } removeByRelation(key, value) { const models = this.get(key, value); if (models === undefined) { return; } const uniqueModelsSet = new Set(models); for (const model of uniqueModelsSet) { const relations = this.#modelToRelationMap.get(model); if (relations === undefined) { throw new Error('Expecting model relation, none found'); } for (const relation of relations) { if (relation[key] === value) { this.#removeModelFromRelationMaps(model, relation); } } this.#modelToRelationMap.delete(model); } } _buildNewInstance(spec) { return new OneToManyMapStar(spec); } _cloneModel(model) { return model; } _cloneRelation(relation) { return relation; } #buildModelToCloneModelMap() { const modelToCloneModelMap = new Map(); for (const model of this.#modelToRelationMap.keys()) { const clonedModel = this._cloneModel(model); modelToCloneModelMap.set(model, clonedModel); } return modelToCloneModelMap; } #buildRelationToRelationModelMap() { const relationToCloneRelationMap = new Map(); for (const relations of this.#modelToRelationMap.values()) { for (const relation of relations) { const clonedRelation = this._cloneRelation(relation); relationToCloneRelationMap.set(relation, clonedRelation); } } return relationToCloneRelationMap; } #buildOrGetModelArray(model) { let relations = this.#modelToRelationMap.get(model); if (relations === undefined) { relations = []; this.#modelToRelationMap.set(model, relations); } return relations; } #buildOrGetRelationModels(relationKey, relationValue) { let models = this.#relationToModelsMaps[relationKey].get(relationValue); if (models === undefined) { models = []; this.#relationToModelsMaps[relationKey].set(relationValue, models); } return models; } #getCloneModel(model, modelToCloneModelMap) { const clonedModel = modelToCloneModelMap.get(model); if (clonedModel === undefined) { throw new Error('Expecting model to be cloned, none found'); } return clonedModel; } #getCloneRelation(relation, relationToCloneRelationMap) { const clonedRelation = relationToCloneRelationMap.get(relation); if (clonedRelation === undefined) { throw new Error('Expecting relation to be cloned, none found'); } return clonedRelation; } #pushModelEntriesIntoModelMap(source, target, modelToCloneModelMap) { for (const [relationValue, models] of source) { const modelsClone = new Array(); for (const model of models) { modelsClone.push(this.#getCloneModel(model, modelToCloneModelMap)); } target.set(relationValue, modelsClone); } } #pushRelationEntriesIntoRelationMap(source, target, modelToCloneModelMap, relationToCloneRelationMap) { for (const [model, relations] of source) { const relationsClone = new Array(); for (const relation of relations) { relationsClone.push(this.#getCloneRelation(relation, relationToCloneRelationMap)); } target.set(this.#getCloneModel(model, modelToCloneModelMap), relationsClone); } } #removeModelFromRelationMaps(model, relation) { for (const relationKey of Reflect.ownKeys(relation)) { this.#removeModelFromRelationMap(model, relationKey, relation[relationKey]); } } #removeModelFromRelationMap(model, relationKey, relationValue) { const relationModels = this.#relationToModelsMaps[relationKey].get(relationValue); if (relationModels !== undefined) { const index = relationModels.indexOf(model); if (index !== NOT_FOUND_INDEX) { relationModels.splice(index, 1); } if (relationModels.length === 0) { this.#relationToModelsMaps[relationKey].delete(relationValue); } } } } exports.OneToManyMapStar = OneToManyMapStar; //# sourceMappingURL=OneToManyMapStar.js.map