@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