blob: b05c8ebfd7959d374c20ed7b21ba5605296cd8c5 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as yaml from 'js-yaml';
import {Integration, CamelElement, Beans} from "../model/IntegrationDefinition";
import {RouteDefinition, NamedBeanDefinition} from "../model/CamelDefinition";
import {CamelUtil} from "./CamelUtil";
import {CamelDefinitionYamlStep} from "./CamelDefinitionYamlStep";
export class CamelDefinitionYaml {
static integrationToYaml = (integration: Integration): string => {
console.log("integrationToYaml");
console.log(integration);
const clone: any = CamelUtil.cloneIntegration(integration);
console.log(clone);
const flows = integration.spec.flows
clone.spec.flows = flows?.map((f: any) => CamelDefinitionYaml.cleanupElement(f)).filter(x => Object.keys(x).length !== 0);
console.log(clone);
if (integration.crd) {
delete clone.crd
const i = JSON.parse(JSON.stringify(clone, null, 3)); // fix undefined in string attributes
console.log(i);
const text = CamelDefinitionYaml.yamlDump(i);
console.log(text);
return text;
} else {
const f = JSON.parse(JSON.stringify(clone.spec.flows, null, 3));
const text = CamelDefinitionYaml.yamlDump(f);
return text;
}
}
static cleanupElement = (element: CamelElement, inArray?: boolean, inSteps?: boolean): CamelElement => {
const result: any = {};
const object: any = Object.assign({}, element);
if (inArray) {
object.inArray = inArray;
object.inSteps = (inSteps === true);
}
if (object.dslName.endsWith('Expression')) {
delete object.language;
delete object.expressionName;
} else if (object.dslName.endsWith('DataFormat')) {
delete object.dataFormatName;
} else if (object.dslName === 'NamedBeanDefinition') {
if (object.properties && Object.keys(object.properties).length === 0) delete object.properties;
}
delete object.uuid;
Object.keys(object)
.forEach(key => {
if (object[key] instanceof CamelElement || (typeof object[key] === 'object' && object[key].dslName)) {
result[key] = CamelDefinitionYaml.cleanupElement(object[key])
} else if (Array.isArray(object[key])) {
if (object[key].length > 0) result[key] = CamelDefinitionYaml.cleanupElements(object[key], key === 'steps')
} else if (key === 'parameters' && typeof (object[key]) === 'object') {
const obj = object[key];
const parameters = Object.keys(obj || {}).reduce((x: any, k) => {
// Check for null or undefined or empty
if (obj[k] !== null && obj[k] !== undefined && obj[k].toString().trim().length > 0) {
x[k] = obj[k];
}
return x;
}, {});
if (Object.keys(parameters).length > 0) result[key] = parameters;
} else {
if (object[key] !== undefined && object[key].toString().trim().length > 0) result[key] = object[key];
}
})
return result as CamelElement
}
static cleanupElements = (elements: CamelElement[], inSteps?: boolean): CamelElement[] => {
const result: any[] = []
elements.forEach(element => {
if (typeof (element) === 'object') {
const newElement = CamelDefinitionYaml.cleanupElement(element, true, inSteps)
result.push(newElement)
} else {
result.push(element);
}
})
return result
}
static yamlDump = (integration: Integration): string => {
return yaml.dump(integration,
{
noRefs: false,
noArrayIndent: false,
sortKeys: function (a: any, b: any) {
if (a === 'uri') return -1
else if (b === 'uri') return 1
else if (a === 'expression' && b == 'steps') return -1
else if (b === 'expression' && a == 'steps') return 1
else if (a === 'steps' && b !== 'uri') return -1
else if (b === 'steps' && a !== 'uri') return 1
else if (a > b) return 1
else return 0;
},
replacer: (key, value) => this.replacer(key, value)
});
}
static replacer = (key: string, value: any): any => {
if (typeof value === 'object' && (value.hasOwnProperty('stepName') || value.hasOwnProperty('inArray') || value.hasOwnProperty('inSteps'))) {
const stepNameField = value.hasOwnProperty('stepName') ? 'stepName' : 'step-name';
const stepName = value[stepNameField];
const dslName = value.dslName;
let newValue: any = JSON.parse(JSON.stringify(value));
delete newValue.dslName;
delete newValue[stepNameField];
if ((value.inArray && !value.inSteps)
|| dslName === 'ExpressionSubElementDefinition'
|| dslName === 'ExpressionDefinition'
|| dslName?.endsWith('Expression')
|| stepName === 'otherwise'
|| key === 'from') {
delete newValue.inArray;
delete newValue.inSteps;
return newValue;
} else {
delete newValue.inArray;
delete newValue.inSteps;
const xValue: any = {};
xValue[stepName] = newValue;
return xValue;
}
} else {
if (value?.dslName && value.dslName.endsWith("Trait") && value.dslName !== 'Trait'){
delete value.dslName;
return {configuration: value};
} else if (value?.dslName === 'Trait' && value?.threeScale){
delete value.dslName;
value["3scale"] = {configuration: value.threeScale};
return value;
}
delete value?.dslName;
return value;
}
}
static yamlToIntegration = (filename: string, text: string): Integration => {
const integration: Integration = Integration.createNew(filename);
const fromYaml: any = yaml.load(text);
const camelized: any = CamelUtil.camelizeObject(fromYaml);
if (camelized?.apiVersion && camelized.apiVersion.startsWith('camel.apache.org') && camelized.kind && camelized.kind === 'Integration') {
integration.crd = true;
if (camelized?.metadata?.name) integration.metadata.name = camelized?.metadata?.name;
const int: Integration = new Integration({...camelized});
integration.spec.flows?.push(...this.flowsToCamelElements(int.spec.flows || []));
} else if (Array.isArray(camelized)) {
integration.crd = false;
const flows: any[] = camelized;
integration.spec.flows?.push(...this.flowsToCamelElements(flows));
}
return integration;
}
static yamlIsIntegration = (text: string): boolean => {
const fromYaml: any = yaml.load(text);
const camelized: any = CamelUtil.camelizeObject(fromYaml);
if (camelized?.apiVersion && camelized.apiVersion.startsWith('camel.apache.org') && camelized.kind && camelized.kind === 'Integration') {
return true;
} else if (Array.isArray(camelized)) {
return true;
} else {
return false;
}
}
static flowsToCamelElements = (flows: any[]): any[] => {
const result: any[] = [];
flows.filter((e: any) => e.hasOwnProperty('restConfiguration'))
.forEach((f: any) => result.push(CamelDefinitionYamlStep.readRestConfigurationDefinition(f.restConfiguration)));
flows.filter((e: any) => e.hasOwnProperty('rest'))
.forEach((f: any) => result.push(CamelDefinitionYamlStep.readRestDefinition(f.rest)));
flows.filter((e: any) => e.hasOwnProperty('route'))
.forEach((f: any) => result.push(CamelDefinitionYamlStep.readRouteDefinition(f.route)));
flows.filter((e: any) => e.hasOwnProperty('from'))
.forEach((f: any) => result.push(CamelDefinitionYamlStep.readRouteDefinition(new RouteDefinition({from: f.from}))));
flows.filter((e: any) => e.hasOwnProperty('beans'))
.forEach((b: any) => result.push(CamelDefinitionYaml.readBeanDefinition(b)));
return result;
}
static readBeanDefinition = (beans: any): Beans => {
const result: Beans = new Beans();
beans.beans.forEach((b: any) => {
const props: any = {}
if (b && b.properties) {
// convert map style to properties if requires
Object.keys(b.properties).forEach(key => {
const value = b.properties[key];
CamelDefinitionYaml.flatMapProperty(key, value, new Map<string, any>())
.forEach((v, k) => props[k] = v);
})
}
b.properties = props;
result.beans.push(new NamedBeanDefinition(b))
})
return result;
}
// convert map style to properties if requires
static flatMapProperty = (key: string, value: any, properties: Map<string, any>): Map<string, any> => {
if (value === undefined) {
} else if (typeof value === 'object') {
Object.keys(value).forEach(k => {
const key2 = key + "." + k;
const value2: any = value[k];
CamelDefinitionYaml.flatMapProperty(key2, value2, new Map<string, any>())
.forEach((value1, key1) => properties.set(key1, value1));
})
} else {
properties.set(key, value);
}
return properties;
}
}