d24486d1500fd43e1e89b07f46b0766944688c99
[sdc/sdc-workflow-designer.git] /
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 import { Component, Input, OnInit } from '@angular/core';
13 import { PlanTreeviewItem } from '../../../../model/plan-treeview-item';
14 import { SwaggerBaseParameter } from '../../../../model/workflow/swagger/swagger-base-parameter';
15 import { SwaggerResponse } from '../../../../model/workflow/swagger/swagger-response';
16 import { TreeNode } from 'primeng/components/common/treenode';
17 import { ValueSource } from '../../../../model/value-source.enum';
18 import { SwaggerIn } from '../../../../model/workflow/swagger/swagger-in.enum';
19 import { SwaggerBodyParameter } from '../../../../model/workflow/swagger/swagger-body-parameter';
20 import { SwaggerTreeConverterService } from '../../../../services/swagger-tree-converter.service';
21 import { SwaggerSchema } from '../../../../model/workflow/swagger/swagger-schema';
22 import { WorkflowUtil } from '../../../../util/workflow-util';
23 import { Parameter } from '../../../../model/workflow/parameter';
24 import { SwaggerNormalParameter } from '../../../../model/workflow/swagger/swagger-normal-parameter';
25 import { ValueType } from '../../../../model/value-type.enum';
26 import { ValueObject } from '../../../../model/value-object';
27
28 @Component({
29   selector: 'wfm-rest-parameters',
30   templateUrl: './rest-parameters.component.html',
31   styleUrls: ['./rest-parameters.component.css']
32 })
33 export class RestParametersComponent implements OnInit {
34   @Input() public dataTypeInput: SwaggerBaseParameter[];
35   @Input() public dataTypeOutput: SwaggerResponse[];
36   @Input() public definitions: any;
37   @Input() public planItems: PlanTreeviewItem[];
38   public queryParams: Parameter[] = [];
39   public headerParams: Parameter[] = [];
40   public pathParams: Parameter[] = [];
41   public formDataParams: Parameter[] = [];
42   public bodyParams: TreeNode[] = [];
43   public responseParams: TreeNode[] = [];
44
45   public inputValueSource = [ValueSource.Variable, ValueSource.Plan, ValueSource.Topology];
46   public outputValueSource = [];
47   constructor() { }
48
49   ngOnInit() {
50     if (this.dataTypeInput) {
51       this.dataTypeInput.forEach(input => {
52         switch (input.in) {
53           case SwaggerIn[SwaggerIn.query]:
54             let query = this.normal2Parameter(input as SwaggerNormalParameter);
55             input.value = query.value;
56             input.valueSource = query.valueSource;
57             this.queryParams.push(query);
58             break;
59           case SwaggerIn[SwaggerIn.header]:
60             let header = this.normal2Parameter(input as SwaggerNormalParameter);
61             input.value = header.value;
62             input.valueSource = header.valueSource;
63             this.headerParams.push(header);
64             break;
65           case SwaggerIn[SwaggerIn.path]:
66             let path = this.normal2Parameter(input as SwaggerNormalParameter);
67             input.value = path.value;
68             input.valueSource = path.valueSource;
69             this.pathParams.push(path);
70             break;
71           case SwaggerIn[SwaggerIn.formData]:
72             let formData = this.normal2Parameter(input as SwaggerNormalParameter);
73             input.value = formData.value;
74             input.valueSource = formData.valueSource;
75             this.formDataParams.push(formData);
76             break;
77           case SwaggerIn[SwaggerIn.body]:
78             let body = this.body2TreeNode(input as SwaggerBodyParameter);
79             input.value = body.value.value;
80             input.valueSource = body.value.valueSource;
81             this.bodyParams.push(body);
82             break;
83           default:
84             console.warn(`Not support this parameters in:${input.in}`);
85             break;
86         }
87       });
88     }
89     this.responseParams.push(this.parameter2TreeNode('status',
90       { type: ValueType[ValueType.number], editable: false }, { value: '', valueSource: ValueSource.string }));
91     if (this.dataTypeOutput) {
92       this.dataTypeOutput.forEach(output => {
93         const treeNode = this.swaggerResponse2TreeNode(output as SwaggerResponse);
94         if (treeNode) {
95           this.responseParams.push(treeNode);
96         }
97       });
98     }
99   }
100
101   public onParamChange(param: Parameter) {
102     this.dataTypeInput.forEach(input => {
103       if (input.name === param.name) {
104         input.value = param.value;
105         input.valueSource = param.valueSource;
106       }
107     });
108   }
109
110   private normal2Parameter(normalParam: SwaggerNormalParameter): Parameter {
111     let finalValue;
112     let finalValueSource;
113     if (normalParam.value && normalParam.value && normalParam.valueSource) {
114       finalValue = normalParam.value;
115       finalValueSource = normalParam.valueSource;
116     } else {
117       finalValue = normalParam.default;
118       finalValueSource = ValueSource[ValueSource.string];
119     }
120     let parameter = new Parameter(normalParam.name, finalValue, finalValueSource, normalParam.type, normalParam.required, normalParam.show);
121     return parameter;
122   }
123
124   private body2TreeNode(bodyParam: SwaggerBodyParameter) {
125     return this.swaggerSchema2TreeNode(bodyParam.name, bodyParam.schema, bodyParam);
126   }
127
128   private swaggerResponse2TreeNode(responseParam: SwaggerResponse): TreeNode {
129     if (responseParam.$ref) {
130       return this.swaggerRef2TreeNode(responseParam.name, responseParam.$ref);
131     } else if (responseParam.schema) {
132       return this.swaggerSchema2TreeNode(responseParam.name, responseParam.schema);
133     } else {
134       console.log(`Unsupport response parameter:${responseParam.name}`);
135       return null;
136     }
137   }
138
139   private swaggerSchema2TreeNode(name: string | number, schema: SwaggerSchema, value?: any) {
140     if (schema.$ref) {
141       return this.swaggerRef2TreeNode(name as string, schema.$ref);
142     } else {
143       value = this.getInitValue4Param(schema, value);
144       return this.parameter2TreeNode(name, schema, value);
145     }
146   }
147
148   private swaggerRef2TreeNode(name: string, ref: string, value?: any) {
149     let definition = this.definitions[ref];
150     let refTreeNode = {
151       label: 'Unsupport Ref Parameter',
152       type: this.getTreeNodeType(ref),
153       required: definition.required,
154       children: [],
155       definition: definition,
156       value: value,
157     };
158
159     // if (value.valueSource === ValueSource[ValueSource.Definition]) {
160     //   if (definition.type === 'object') {
161     //     refTreeNode.children = this.getPropertyFromObject(definition, value.value);
162     //   } else if (definition.type === 'array') {
163     //     refTreeNode.children = this.setChildrenForArray(definition, value.value);
164     //   }
165     // }
166     return refTreeNode;
167   }
168
169   private getInitValue4Param(schema: SwaggerSchema, value: any) {
170     let definition = schema;
171     if (schema.$ref) {
172       definition = this.definitions[schema.$ref];
173     }
174     let valueObject: ValueObject = { valueSource: ValueSource[ValueSource.string] };
175     if (undefined == value) {
176       valueObject.value = definition.default;
177       if (ValueType[ValueType.array] === definition.type || ValueType[ValueType.object] === definition.type) {
178         valueObject.valueSource = ValueSource[ValueSource.Definition];
179       } else {
180         valueObject.valueSource = definition.type;
181       }
182     } else {
183       if('object' != typeof(value)){
184         console.error('Param value is not object!, param definition is:' + definition);
185       }
186       valueObject.valueSource = value.valueSource;
187       valueObject.value = undefined === value.value ? definition.default : value.value;
188     }
189     if (ValueType[ValueType.object] === definition.type) {
190       return this.getInitValue4Object(valueObject);
191     } else if (ValueType[ValueType.array] === definition.type) {
192       // if (undefined == value) {
193       //   valueObject.value = definition.default;
194       //   if (ValueType[ValueType.array] === definition.type || ValueType[ValueType.object] === definition.type) {
195       //     valueObject.valueSource = ValueSource[ValueSource.Definition];
196       //   } else {
197       //     valueObject.valueSource = definition.type;
198       //   }
199       // } else {
200       //   valueObject.valueSource = value.valueSource;
201       //   valueObject.value = undefined === value.value ? definition.default : value.value;
202       // }
203       return this.getInitValue4Array(valueObject);
204     } else { // primary type
205       // valueObject.value = undefined === value ? definition.default : value;
206       // valueObject.valueSource = definition.type;
207       return this.getInitValue4Primary(valueObject);
208     }
209   }
210
211
212   private getInitValue4Object(value: any) {
213     const newValue = {
214       value: {},
215       valueSource: ValueSource[ValueSource.Definition]
216     };
217
218     if (!value || '' === value) {
219       return newValue;
220     } else {
221       if (value.valueSource !== ValueSource[ValueSource.Definition]) {
222         return value;
223       } else {
224         if (typeof value.value !== 'object') {
225           value.value = {};
226         }
227         return value;
228       }
229     }
230   }
231
232   private getInitValue4Array(value: any) {
233     const newValue = {
234       value: [],
235       valueSource: ValueSource[ValueSource.Definition]
236     };
237
238     if (!value || '' === value) {
239       return newValue;
240     } else {
241       if (value.valueSource !== ValueSource[ValueSource.Definition]) {
242         return value;
243       } else {
244         if (!(value.value instanceof Array)) {
245           value.value = [];
246         }
247         return value;
248       }
249     }
250   }
251
252   private getInitValue4Primary(value: any) {
253     const newValue = {
254       value: '',
255       valueSource: ValueSource[ValueSource.string]
256     };
257
258     if (!value) {
259       return newValue;
260     } else {
261       if (typeof value.value === 'object') {
262         value.value = '';
263       }
264       return value;
265     }
266   }
267
268   private parameter2TreeNode(name: string | number, definition: any, value: any): any {
269     const nodeType = this.getTreeNodeType(definition);
270
271     const node = {
272       label: name,
273       type: nodeType,
274       required: definition.required,
275       children: [],
276       definition: definition,
277       value: value
278     };
279
280     if (value.valueSource === ValueSource[ValueSource.Definition]) {
281       if (ValueType[ValueType.object] === definition.type) {
282         node.children = this.getPropertyFromObject(definition, value.value);
283       } else if (ValueType[ValueType.array] === definition.type) {
284         node.children = this.getItemsFromArray(definition, value.value);
285       }
286     }
287
288     return node;
289   }
290
291   private getTreeNodeType(param: any): string {
292     const type = param.type;
293     if (ValueType[ValueType.array] === type) {
294       return 'array';
295     } else if (ValueType[ValueType.object] === type) {
296       if (param.additionalProperties) {
297         return 'map';
298       } else {
299         return 'object';
300       }
301     } else {
302       return 'default';
303     }
304   }
305
306   private getPropertyFromObject(schema: SwaggerSchema, value: any): TreeNode[] {
307     if (schema.properties) {
308       const required = schema.required as string[];
309       return this.getPropertyFromSimpleObject(schema.properties, value, required);
310     } else if (schema.additionalProperties) {
311       return this.getPropertyFromMapOrDictionary(schema.additionalProperties, value);
312     } else {
313       console.warn('getPropertyFromObject() return [], param is:' + JSON.stringify(schema));
314       return [];
315     }
316
317   }
318
319   private getPropertyFromSimpleObject(properties: any, objectValue: any, required: string[]): TreeNode[] {
320     const treeNodes: TreeNode[] = [];
321     for (const key in properties) {
322       let property = properties[key];
323       // init required property
324       property.required = false;
325       if (Array.isArray(required)) {
326         for (let index = 0; index < required.length; index++) {
327           if (required[index] === key) {
328             property.required = true;
329             break;
330           }
331         }
332       }
333
334       objectValue[key] = this.getInitValue4Param(property, objectValue[key]);
335
336       const treeNode = this.swaggerSchema2TreeNode(key, property, objectValue[key]);
337       treeNodes.push(treeNode);
338     }
339     return treeNodes;
340   }
341
342   private getPropertyFromMapOrDictionary(additionalProperties: any, mapOrDictionary: any): TreeNode[] {
343     const treeNodes: TreeNode[] = [];
344     for (const key in mapOrDictionary) {
345       const propertyCopy = WorkflowUtil.deepClone(additionalProperties);
346       propertyCopy.value = mapOrDictionary[key];
347       const treeNode = this.swaggerSchema2TreeNode(key, propertyCopy, propertyCopy.value);
348       treeNode.keyEditable = true;
349       treeNodes.push(treeNode);
350       if (mapOrDictionary[key] !== propertyCopy.value) {
351         mapOrDictionary[key] = propertyCopy.value;
352       }
353     }
354     return treeNodes;
355   }
356
357   private getItemsFromArray(definition: any, value: any[]): any[] {
358     const children = [];
359     value.forEach((itemValue, index) => {
360       const itemCopy = WorkflowUtil.deepClone(definition.items);
361       children.push(this.swaggerSchema2TreeNode(index, itemCopy, itemValue));
362     });
363
364     return children;
365   }
366
367 }