@yellicode/elements
Version:
The meta model API for Yellicode - an extensible code generator.
176 lines (175 loc) • 8.04 kB
JavaScript
/*
* Copyright (c) 2020 Yellicode
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
import * as Interfaces from "./interfaces";
import { ElementTypeUtility } from './utils';
import { BasicTypeResolver } from './type-resolver';
var ElementMapImpl = /** @class */ (function () {
function ElementMapImpl(customTypeResolver) {
this.elementsById = {};
this.specializationsById = {};
this.associationsByEndId = {};
this.externalTypeResolver = new BasicTypeResolver(customTypeResolver);
// TODO: do we need UnlimitedNatural? If so, it should be exported by './primitives'.
}
ElementMapImpl.prototype.addElement = function (element, elementData) {
if (this.elementsById.hasOwnProperty(element.id)) {
if (element.elementType !== Interfaces.ElementType.primitiveType)
console.warn("Duplicate element id '" + element.id + "'.");
return;
}
this.elementsById[element.id] = element;
// TODO: the elementData argument and the lines below should be removed
// once the DataToModelConverter is replaced by the ModelSerializer.
// Add generalizations to the specialization map
if (ElementTypeUtility.isClassifier(element.elementType) && elementData) {
this.addSpecializations(element, elementData);
}
// Add association ends to the assciationEnd map
if (ElementTypeUtility.isAssociation(element.elementType) && elementData) {
this.addAssociationEnds(element, elementData);
}
};
ElementMapImpl.prototype.addAssociationEnds = function (association, associationData) {
var _this = this;
// Get memberEnds of assocationData instead of association itself: the ends will not be set here as they are not resolved yet
// by DataToModelConverter.resolveAssociationReferences().
if (!associationData.memberEnds)
return;
associationData.memberEnds.forEach(function (endId) {
// An association end can only be part of one association.
_this.addAssociationByEndId(endId, association);
});
};
ElementMapImpl.prototype.addAssociationByEndId = function (endId, association) {
// An association end can only be part of one association.
if (this.associationsByEndId.hasOwnProperty(endId)) {
console.warn("Association end with id '" + endId + "' is already part of another association than " + association.id + ".");
}
this.associationsByEndId[endId] = association;
};
ElementMapImpl.prototype.removeAssociationByEndId = function (endId) {
delete this.associationsByEndId[endId];
};
ElementMapImpl.prototype.addSpecializations = function (classifier, classifierData) {
var _this = this;
if (!classifierData.generalizations)
return;
// Enumerate the classifierData instead of the classifier itself: the generalizations will not be set here as they are not resolved yet
classifierData.generalizations.forEach(function (g) {
// g is a Generalization of element, so element is a Specialization of g
_this.addSpecialization(g.general, classifier);
// if (this.specializationsById.hasOwnProperty(g.general)) {
// dictionaryEntry = this.specializationsById[g.general];
// dictionaryEntry.push(classifier);
// } else {
// this.specializationsById[g.general] = [classifier];
// }
});
};
ElementMapImpl.prototype.addSpecialization = function (generalId, specialization) {
var dictionaryEntry;
if (this.specializationsById.hasOwnProperty(generalId)) {
dictionaryEntry = this.specializationsById[generalId];
dictionaryEntry.push(specialization);
}
else {
this.specializationsById[generalId] = [specialization];
}
};
ElementMapImpl.prototype.removeSpecialization = function (generalId, specialization) {
if (!this.specializationsById.hasOwnProperty(generalId))
return;
var dictionaryEntry = this.specializationsById[generalId];
var ix = dictionaryEntry.indexOf(specialization);
if (ix > -1)
dictionaryEntry.splice(ix, 1);
};
// public removeGeneral(generalId: string): void {
// if (!this.specializationsById.hasOwnProperty(generalId))
// return;
// // First remove the general from all it's specializations
// const dictionaryEntry = this.specializationsById[generalId];
// dictionaryEntry.forEach(specialization => {
// const ix = specialization.generalizations.findIndex(g => g.general.id === generalId);
// if (ix > -1)
// specialization.generalizations.splice(ix, 1);
// })
// // Then remove from the map entirely
// delete this.specializationsById[generalId];
// }
ElementMapImpl.prototype.getAssociationHavingMemberEnd = function (end) {
if (!end || !end.id)
return null;
if (!this.associationsByEndId.hasOwnProperty(end.id))
return null;
return this.associationsByEndId[end.id];
};
ElementMapImpl.prototype.hasElement = function (id) {
return this.elementsById.hasOwnProperty(id);
};
ElementMapImpl.prototype.getElementById = function (id) {
if (!id || id.length === 0)
return null;
// Is the element an external or built-in type?
var externalType = this.externalTypeResolver.resolve(id);
if (externalType)
return externalType;
if (this.elementsById.hasOwnProperty(id))
return this.elementsById[id];
else {
// console.warn(`Unkown element id '${id}'.`);
return null;
}
};
ElementMapImpl.prototype.getElementsByIdList = function (idList) {
var _this = this;
var result = [];
if (idList == null)
return result;
idList.forEach(function (id) {
var element = _this.getElementById(id);
if (element != null)
result.push(element);
});
return result;
};
ElementMapImpl.prototype.getSpecializationsOf = function (generalId) {
if (!this.specializationsById.hasOwnProperty(generalId))
return [];
return this.specializationsById[generalId];
};
ElementMapImpl.prototype.getAllSpecializationsOf = function (generalId) {
if (!this.specializationsById.hasOwnProperty(generalId))
return [];
var specialMap = {};
this.getAllSpecializationsRecursive(generalId, specialMap);
// Convert the result to an array
var result = [];
for (var specializationId in specialMap) {
result.push(specialMap[specializationId]);
}
return result;
};
ElementMapImpl.prototype.getAllSpecializationsRecursive = function (generalId, specialMap) {
var _this = this;
if (!this.specializationsById.hasOwnProperty(generalId)) {
return;
}
var directSpecializations = this.specializationsById[generalId];
directSpecializations.forEach(function (s) {
if (!specialMap.hasOwnProperty(s.id) &&
!s.isOrphaned()) {
specialMap[s.id] = s;
}
// Get the specializations of this specialization
_this.getAllSpecializationsRecursive(s.id, specialMap);
});
};
return ElementMapImpl;
}());
export { ElementMapImpl };