@ui5/task-adaptation
Version:
Custom task for ui5-builder which allows building UI5 Flexibility Adaptation Projects for SAP BTP, Cloud Foundry environment
66 lines • 3.63 kB
JavaScript
import MetadataJsonUtil from "../converter/metadataJsonUtil.js";
import DataSourceODataAnnotation from "../dataSource/dataSourceODataAnnotation.js";
import UrlUtil from "../../util/urlUtil.js";
export default class TraverseReferences {
metadataUrl;
constructor(metadataUrl) {
this.metadataUrl = metadataUrl;
}
async transform({ json, language, serviceRequestor, uri: parentUrl }) {
const references = MetadataJsonUtil.getReferences(json).filter(TraverseReferences.isTraversable);
const promises = [];
for (const { includes, uri: relativeUrl } of references) {
const resourcePath = UrlUtil.getResourcePath(relativeUrl);
const absoluteUrl = UrlUtil.join(resourcePath, parentUrl);
if (this.shouldIgnoreUrl(absoluteUrl, [parentUrl, this.metadataUrl])) {
// If reference to metadata or its parent, don't traverse
continue;
}
const name = includes[0]?.namespace;
const dataSource = new DataSourceODataAnnotation(name, absoluteUrl, {}, this.metadataUrl);
promises.push(dataSource.downloadAnnotation(language, serviceRequestor)
.then(childAnnotation => ({ name, childAnnotation })));
}
const childAnnotations = await Promise.all(promises);
for (const { childAnnotation } of childAnnotations) {
this.mergeAnnotations(json, childAnnotation);
}
return json;
}
shouldIgnoreUrl(referenceUrl, urlsToIgnore) {
const toResourcePath = (url) => url && UrlUtil.getResourcePath(url);
const isEqual = (a, b) => a && b && a.toLowerCase() === b.toLowerCase();
return urlsToIgnore.map(toResourcePath).some(url => isEqual(referenceUrl, url));
}
mergeAnnotations(parentJson, nestedJson) {
const parentAnnotations = MetadataJsonUtil.getAnnotations(parentJson);
const parentMapByTarget = MetadataJsonUtil.mapAnnotationsPerTarget(parentJson);
const nestedMapByTarget = MetadataJsonUtil.mapAnnotationsPerTarget(nestedJson);
for (const nested of [...nestedMapByTarget].map(([target, { json }]) => ({ target, json }))) {
// If we found parent annotation with the same target - we extend it
// with missing <Annotation> nodes. If not, just add it to the end.
// Annotations do not have a merge logic If same target & term is in
// parent and nested, parent wins (same logic as UI5 in
// sap/ui/model/odata/v4/ODataMetaModel.js mergeAnnotations).
const parent = parentMapByTarget.get(nested.target);
if (parent) {
MetadataJsonUtil.toArrayTransform(parent.json, "Annotation");
const parentTerms = parent.json.Annotation.map((item) => item._attributes.Term);
for (const nestedAnnotation of MetadataJsonUtil.toArrayReadOnly(nested.json.Annotation)) {
if (!parentTerms.includes(nestedAnnotation._attributes.Term)) {
parent.json.Annotation.push(nestedAnnotation);
}
}
}
else {
parentAnnotations.push(nested.json);
}
}
MetadataJsonUtil.setAnnotations(parentJson, parentAnnotations);
}
static isTraversable(reference) {
const IGNORED_NAMESPACES = ["com.sap.vocabularies.", "Org.OData."];
return !reference.includes.some(include => IGNORED_NAMESPACES.some(namespace => include.namespace.startsWith(namespace)));
}
}
//# sourceMappingURL=traverseReferences.js.map