support set body parameter by json
[sdc/sdc-workflow-designer.git] / sdc-workflow-designer-ui / src / app / services / swagger-tree-converter.service.ts
1 /*******************************************************************************
2  * Copyright (c) 2017 ZTE Corporation.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * and the Apache License 2.0 which both accompany this distribution,
6  * and are available at http://www.eclipse.org/legal/epl-v10.html
7  * and http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Contributors:
10  *     ZTE - initial API and implementation and/or initial documentation
11  *******************************************************************************/
12
13 import { Injectable } from '@angular/core';
14 import { TreeNode } from 'primeng/primeng';
15
16 import { ValueSource } from '../model/value-source.enum';
17 import { WorkflowUtil } from '../util/workflow-util';
18 import { WorkflowConfigService } from "./workflow-config.service";
19
20 @Injectable()
21 export class SwaggerTreeConverterService {
22     private serviceName: string;
23     private serviceVersion: string;
24
25     constructor(private configService: WorkflowConfigService) {
26
27     }
28
29     public schema2TreeNode(key: string | number, serviceName: string, serviceVersion: string, schema: any): any {
30         this.serviceName = serviceName;
31         this.serviceVersion = serviceVersion;
32
33         if (schema.$ref) {
34             const treeNode = this.getTreeNodeBySwaggerDefinition(key, schema);
35             return treeNode;
36         } else {
37             this.setInitValue4Param(schema.value, schema);
38             return this.parameter2TreeNode(key, schema);
39         }
40     }
41
42     private getTreeNodeBySwaggerDefinition(key: string | number, schema: any): TreeNode {
43         const swagger = this.configService.getSwaggerInfo(this.serviceName, this.serviceVersion);
44         if(swagger === undefined) {
45             console.log(`swagger definition not exist, [${this.serviceName}].[${this.serviceVersion}]`);
46             return null;
47         }
48         const swaggerDefinition = this.configService.getDefinition(swagger, schema.$ref);
49
50         const definitionCopy = WorkflowUtil.deepClone(swaggerDefinition);
51
52         this.setInitValue4Param(schema.value, definitionCopy);
53         if (schema.value !== definitionCopy.value) {
54             schema.value = definitionCopy.value;
55         }
56
57         return this.schema2TreeNode(key, this.serviceName, this.serviceVersion, definitionCopy);
58     }
59
60     private setInitValue4Param(value: any | any[], param: any) {
61         param.value = value;
62         if (value == null) {
63             if (param.type === 'object') {
64                 param.value = {};
65             } else if (param.type === 'array') {
66                 param.value = [];
67             } else { // primary type
68                 param.valueSource = ValueSource[ValueSource.String];
69             }
70         }
71     }
72
73     private parameter2TreeNode(name: string | number, paramDefinition: any): any {
74         const nodeType = this.getTreeNodeType(paramDefinition);
75
76         const node = {
77             label: name,
78             type: nodeType,
79             children: [],
80             parameter: paramDefinition,
81         };
82
83         if (paramDefinition.type === 'object') {
84             node.children = this.getPropertyFromObject(paramDefinition.value, paramDefinition);
85         } else if (paramDefinition.type === 'array') {
86             this.setChildrenForArray(node, paramDefinition);
87         }
88
89         return node;
90     }
91
92     private getTreeNodeType(param: any): string {
93         const type = param.type;
94         if (type === 'array') {
95             return 'array';
96         } else if (type === 'object') {
97             if (param.additionalProperties) {
98                 return 'map';
99             } else {
100                 return 'object';
101             }
102         } else {
103             return 'default';
104         }
105     }
106
107     private setChildrenForArray(node: any, param: any) {
108         param.value.forEach((itemValue, index) => {
109             const itemCopy = WorkflowUtil.deepClone(param.items);
110             itemCopy.value = itemValue;
111             node.children.push(this.schema2TreeNode(index, this.serviceName, this.serviceVersion, itemCopy));
112         });
113     }
114
115     private getPropertyFromObject(objectValue: any, param: any): TreeNode[] {
116         if (param.properties) {
117             return this.getPropertyFromSimpleObject(objectValue, param.properties);
118         } else if (param.additionalProperties) {
119             return this.getPropertyFromMapOrDictionary(objectValue, param.additionalProperties);
120         } else {
121             return [];
122         }
123
124     }
125
126     private getPropertyFromSimpleObject(objectValue: any, properties: any): TreeNode[] {
127         const treeNodes: TreeNode[] = [];
128         for (const key in properties) {
129             const property = properties[key];
130             this.setInitValue4Param(objectValue[key], property);
131
132             if (property.value !== objectValue[key]) {
133                 objectValue[key] = property.value;
134             }
135
136             treeNodes.push(this.schema2TreeNode(key, this.serviceName, this.serviceVersion, property));
137         }
138         return treeNodes;
139     }
140
141     private getPropertyFromMapOrDictionary(mapOrDictionary: any, additionalProperties: any): TreeNode[] {
142         const treeNodes: TreeNode[] = [];
143         for (const key in mapOrDictionary) {
144             const propertyCopy = WorkflowUtil.deepClone(additionalProperties);
145             propertyCopy.value = mapOrDictionary[key];
146
147             const treeNode = this.schema2TreeNode(key, this.serviceName, this.serviceVersion, propertyCopy);
148             treeNode.keyEditable = true;
149             treeNodes.push(treeNode);
150
151             if (mapOrDictionary[key] !== propertyCopy.value) {
152                 mapOrDictionary[key] = propertyCopy.value;
153             }
154         }
155         return treeNodes;
156     }
157 }