UNPKG

@ui5/task-adaptation

Version:

Custom task for ui5-builder which allows building UI5 Flexibility Adaptation Projects for SAP BTP, Cloud Foundry environment

252 lines 9.93 kB
import UI5JsonParser from "./ui5MetadataJsonUtil.js"; export default class UI5JsonConverter { config; oAnnotationConfig; static convertAnnotations(json) { const annotationsNode = UI5JsonParser.getAnnotationsNode(json); if (annotationsNode) { return Object.entries(annotationsNode).map(([target, annotations]) => this.processAnnotations(annotations, target)); } return []; } static processAnnotations(json, target) { const attributes = { "_attributes": { "Target": this.trimLeft(target, "@") } }; const annotation = this.processTerms(json); return Object.assign(attributes, annotation); } static processObject(term, value) { let wrapped = this.getWrappedProperty(value); if (wrapped) { this.getAttributes(term)[wrapped.property] = wrapped.value; } else { const record = this.processTerms(value); this.updateToArray(term, "Record", record); } } static processTerms(json) { let result = {}; const pendingInlineAnnotationKeys = new Array(); for (const key of Object.keys(json)) { let wrapped = this.getWrappedProperty(json); const inlineAnnotation = this.getInlineAnnotation(key); if (inlineAnnotation) { pendingInlineAnnotationKeys.push(inlineAnnotation); continue; } if (wrapped) { this.getAttributes(result)[wrapped.property] = wrapped.value; } else if (key.startsWith("$")) { this.getAttributes(result)[this.trimLeft(key, "$")] = json[key]; } else { // Split Annotation from PropertyValue const options = (key[0] === "@") ? { attributesProperty: "Term", entity: "Annotation" } : { attributesProperty: "Property", entity: "PropertyValue", explicitBoolean: true }; const term = this.createTerm(key, options.attributesProperty); const value = json[key]; if (typeof value === "string") { term._attributes.String = value; } else if (typeof value === "boolean" && (!value || options.explicitBoolean)) { term._attributes.Bool = value.toString(); } else if (typeof value === "number") { term._attributes.Int = value.toString(); } else if (Array.isArray(value)) { this.processCollection(term, value); } else if (typeof value === "object") { this.processObject(term, value); } this.updateToArray(result, options.entity, term); } } for (const inlineAnnotation of pendingInlineAnnotationKeys) { const { term, reference } = inlineAnnotation; if (inlineAnnotation.isInlineAnnotationWithCollections) { // TODO can possibly be merged with below this.processInlineAnnotationWithCollections(inlineAnnotation, json, result); } else if (Array.isArray(json[inlineAnnotation.key])) { const annotationTerm = { Annotation: this.createTerm(term, "Term") }; this.processCollection(annotationTerm.Annotation, json[inlineAnnotation.key]); if (Array.isArray(result[inlineAnnotation.entity])) { let referenced = result[inlineAnnotation.entity].find((item) => this.isReferenced(item, inlineAnnotation.attributesProperty, reference)); if (referenced) { referenced = Object.assign(referenced, annotationTerm); } } else if (result[inlineAnnotation.entity]) { result[inlineAnnotation.entity] = Object.assign(result[inlineAnnotation.entity], annotationTerm); } } else { const annotation = this.processAnnotation(json, inlineAnnotation.key, term); if (Array.isArray(result[inlineAnnotation.entity])) { const referenced = result[inlineAnnotation.entity].find((item) => this.isReferenced(item, inlineAnnotation.attributesProperty, reference)); if (referenced) { referenced.Annotation = annotation; } } else if (result[inlineAnnotation.entity]) { result[inlineAnnotation.entity].Annotation = annotation; } } } return result; } static processInlineAnnotationWithCollections(inlineAnnotation, json, result) { delete Object.assign(json, { [`@${inlineAnnotation.term}`]: json[inlineAnnotation.key] })[inlineAnnotation.key]; const term = this.createTerm(inlineAnnotation.term, "Term"); this.processCollection(term, json[`@${inlineAnnotation.term}`]); const PropertyValue = (Array.isArray(result.PropertyValue)) ? result.PropertyValue : [result.PropertyValue]; const targetProperty = PropertyValue.find((propertyValueObject) => { return this.isReferenced(propertyValueObject, "Property", inlineAnnotation.reference); }); if (targetProperty) { this.updateToArray(targetProperty, "Annotation", term); } } static isReferenced(item, attributesProperty, reference) { return this.getAttributes(item) && this.getAttributes(item)[attributesProperty] === reference; } static processAnnotation(json, key, term = key) { const annotation = this.processTerms(json[key]); const annotationTerm = this.trimByAt(term); const attributes = this.getAttributes(annotation); if (Object.keys(attributes).length > 0 && annotationTerm) { annotation._attributes = Object.assign({ "Term": annotationTerm }, attributes); } else { this.getAttributes(annotation).Term = annotationTerm; } return annotation; } static getInlineAnnotation(key) { const parts = key.split("@"); // @<ref>@<term> if (parts.length === 3) { return { reference: parts[1], term: parts[2], key, attributesProperty: "Term", entity: "Annotation" }; } else if (parts.length === 2 && parts[0]) { // <ref>@<term> return { reference: parts[0], term: parts[1], key, isInlineAnnotationWithCollections: true, attributesProperty: "Property", entity: "PropertyValue", }; } } static createTerm(key, attributesProperty) { const parts = key.split("#"); const qualifier = parts.length > 1 && parts.pop(); const term = { "_attributes": { [attributesProperty]: this.trimByAt(parts[0]) } }; if (qualifier) { term._attributes.Qualifier = qualifier; } return term; } static processCollection(term, value) { const collection = term.Collection = {}; for (const item of value) { this.processCollectionItem(collection, item); } } static processCollectionItem(collection, item) { let wrapped = this.getWrappedProperty(item); if (wrapped) { this.updateToArray(collection, wrapped.property, wrapped.value.length > 0 ? { _text: wrapped.value } : {}); } else if (typeof item === "string") { this.updateToArray(collection, "String", { _text: item }); } else if (typeof item === "object") { this.processObject(collection, item); } } static updateToArray(object, key, value) { if (object[key]) { if (!Array.isArray(object[key])) { object[key] = [object[key]]; } object[key].push(value); } else { object[key] = value; } } static getAttributes(parent) { if (parent._attributes == null) { parent._attributes = {}; } return parent._attributes; } static trimLeft(str, char) { while (str.startsWith(char)) { str = str.substring(1); } return str; } static trimByAt(term) { const indexOfAt = term.indexOf("@"); if (indexOfAt > -1) { return term.substring(indexOfAt + 1); } return term; } static isWrapped(type) { // copied from openUI5 _MetadataConverter.js switch (type) { case "$AnnotationPath": case "$NavigationPropertyPath": case "$Path": case "$PropertyPath": case "$Binary": case "$Date": case "$DateTimeOffset": case "$Decimal": case "$Duration": case "$Guid": case "$TimeOfDay": case "$UrlRef": case "$EnumMember": return true; } } static getWrappedProperty(item) { if (typeof item === "object") { const keys = Object.keys(item); if (keys.length === 1 && this.isWrapped(keys[0])) { return { property: keys[0].substring(1), value: item[keys[0]] }; } } } } //# sourceMappingURL=ui5JsonConverter.js.map