@yellicode/elements
Version:
The meta model API for Yellicode - an extensible code generator.
103 lines (102 loc) • 5.27 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/.
*/
// Prioritizes which keys should be resolved before others. For example, before resolving Element.appliedStereotypes
// (where we process tagged values), we should have resolved TaggedValueSpecification.definition.
var resolutionPriority = ['definition', 'appliedStereotypes'];
var ElementReferenceResolver = /** @class */ (function () {
function ElementReferenceResolver(modelDelegate) {
this.modelDelegate = modelDelegate;
/**
* Contains a list of unresolved references, grouped by key (that is, the name of the
* referring property).
*/
this.unResolvedReferencesByKey = {};
}
ElementReferenceResolver.prototype.addUnResolvedReference = function (key, referrer, elementId) {
var isArray = false;
var collection;
if (Array.isArray(elementId)) {
collection = elementId;
isArray = true;
}
else
collection = [elementId];
var referencesForKey = this.unResolvedReferencesByKey[key];
if (!referencesForKey) {
this.unResolvedReferencesByKey[key] = referencesForKey = { isArrayProperty: isArray, referrersByElementId: {} };
}
collection.forEach(function (elementId) {
var referrers = referencesForKey.referrersByElementId[elementId];
if (!referrers)
referencesForKey.referrersByElementId[elementId] = referrers = [];
referrers.push(referrer);
});
};
ElementReferenceResolver.prototype.resolve = function () {
var _this = this;
Object.keys(this.unResolvedReferencesByKey)
.sort(function (a, b) { return resolutionPriority.indexOf(a) - resolutionPriority.indexOf(b); })
.forEach(function (key) {
var group = _this.unResolvedReferencesByKey[key];
Object.keys(group.referrersByElementId).forEach(function (elementId) {
var referredElement = _this.modelDelegate.findElementById(elementId);
var referrers = group.referrersByElementId[elementId];
if (!referredElement)
return console.warn(referrers.length + " elements have a '" + key + "' reference with unresolvable id " + elementId + ".");
referrers.forEach(function (referrer) {
// console.log(`${(referrer as NamedElement).name || referrer.id} has ${key} ${elementId}. Array: ${group.isArrayProperty}`);
if (group.isArrayProperty) {
var array = referrer[key];
if (!array) { // ensure an array (although it should already be initialized)
referrer[key] = array = [];
}
array.push(referredElement);
}
else
referrer[key] = referredElement;
// Apply custom logic to some relationships
switch (key) {
case 'general':
// Even though there is a onGeneralizationAdded call in modelDelegate.createElement(),
// that call doesn't have any effect without a general.
_this.modelDelegate.onGeneralizationAdded(referrer);
break;
case 'memberEnds':
_this.modelDelegate.onMemberEndAdded(referrer, referredElement);
break;
case 'appliedStereotypes':
_this.applyStereotype(referrer, referredElement);
break;
}
});
});
});
this.unResolvedReferencesByKey = {};
};
ElementReferenceResolver.prototype.applyStereotype = function (element, st) {
if (!element.taggedValues || !element.taggedValues.length)
return;
var stereotypeMetaProperties = st.getAllAttributes(); // stereotypes can inherit other stereotypes
stereotypeMetaProperties.forEach(function (metaProperty) {
if (element.hasOwnProperty(metaProperty.name))
return;
// Extend the element with the property. But determine the value first.
var valueSpecification = null;
var taggedValue = element.taggedValues.find(function (v) { return v.definition.id === metaProperty.id; });
if (taggedValue) {
valueSpecification = taggedValue.specification;
}
else if (metaProperty.defaultValue) {
valueSpecification = metaProperty.defaultValue;
}
element[metaProperty.name] = valueSpecification ? valueSpecification.getValue() : null;
});
};
return ElementReferenceResolver;
}());
export { ElementReferenceResolver };