8128b44c244d2d4798fe0e18d8141444a6f35309
[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
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 { RestService } from './rest.service';
19 import { Swagger } from "../model/swagger";
20 import { ValueObject } from '../model/value-object';
21 import { ValueType } from '../model/value-type.enum';
22
23 @Injectable()
24 export class SwaggerTreeConverterService {
25
26   private swagger: Swagger;
27
28   constructor(private restService: RestService) { }
29
30   public schema2TreeNode(swagger: Swagger, key: string | number, schema: any, value?: any): any {
31     this.swagger = swagger;
32     if (schema.$ref) {
33       const treeNode = this.getTreeNodeBySwaggerDefinition(key, schema, value);
34       return treeNode;
35     } else {
36       value = this.getInitValue4Param(schema, value);
37       return this.parameter2TreeNode(key, schema, value);
38     }
39   }
40
41   private getTreeNodeBySwaggerDefinition(key: string | number, schema: any, value: any): TreeNode {
42     const swaggerDefinition = this.restService.getDefinition(this.swagger, schema.$ref);
43
44     const definitionCopy = WorkflowUtil.deepClone(swaggerDefinition);
45
46     value = this.getInitValue4Param(definitionCopy, value);
47
48     return this.schema2TreeNode(this.swagger, key, definitionCopy, value);
49   }
50
51   private getInitValue4Param(definition: any, value: any) {
52     if (definition.$ref) {
53       definition = this.restService.getDefinition(this.swagger, definition.$ref);
54     }
55     let valueObject: ValueObject = { valueSource: ValueSource[ValueSource.string] };
56     if (undefined == value) {
57       valueObject.value = definition.default;
58       if (ValueType[ValueType.array] === definition.type || ValueType[ValueType.object] === definition.type) {
59         valueObject.valueSource = ValueSource[ValueSource.Definition];
60       } else {
61         valueObject.valueSource = definition.type;
62       }
63     } else {
64       valueObject.valueSource = value.valueSource;
65       valueObject.value = undefined === value.value ? definition.default : value.value;
66     }
67     if (definition.type === 'object') {
68       // if (undefined == value) {
69       //   valueObject.value = definition.default;
70       //   if (ValueType[ValueType.array] === definition.type || ValueType[ValueType.object] === definition.type) {
71       //     valueObject.valueSource = ValueSource[ValueSource.Definition];
72       //   } else {
73       //     valueObject.valueSource = definition.type;
74       //   }
75       // } else {
76       //   valueObject.valueSource = value.valueSource;
77       //   valueObject.value = undefined === value.value ? definition.default : value.value;
78       // }
79       return this.getInitValue4Object(valueObject);
80     } else if (definition.type === 'array') {
81       return this.getInitValue4Array(valueObject);
82     } else { // primary type
83       // valueObject.value = undefined === value ? definition.default : value;
84       // valueObject.valueSource = definition.type;
85       return this.getInitValue4Primary(valueObject);
86     }
87   }
88
89   private getInitValue4Object(value: any) {
90     const newValue = {
91       value: {},
92       valueSource: ValueSource[ValueSource.Definition]
93     };
94
95     if (!value || '' === value) {
96       return newValue;
97     } else {
98       if (value.valueSource !== ValueSource[ValueSource.Definition]) {
99         return value;
100       } else {
101         if (typeof value.value !== 'object') {
102           value.value = {};
103         }
104         return value;
105       }
106     }
107   }
108
109   private getInitValue4Array(value: any) {
110     const newValue = {
111       value: [],
112       valueSource: ValueSource[ValueSource.Definition]
113     };
114
115     if (!value || '' === value) {
116       return newValue;
117     } else {
118       if (value.valueSource !== ValueSource[ValueSource.Definition]) {
119         return value;
120       } else {
121         if (!(value.value instanceof Array)) {
122           value.value = [];
123         }
124         return value;
125       }
126     }
127   }
128
129   private getInitValue4Primary(value: any) {
130     const newValue = {
131       value: '',
132       valueSource: ValueSource[ValueSource.string]
133     };
134
135     if (!value) {
136       return newValue;
137     } else {
138       if (typeof value.value === 'object') {
139         value.value = '';
140       }
141       return value;
142     }
143   }
144
145   private parameter2TreeNode(name: string | number, definition: any, value: any): any {
146     const nodeType = this.getTreeNodeType(definition);
147
148     const node = {
149       label: name,
150       type: nodeType,
151       required: definition.required,
152       children: [],
153       definition: definition,
154       value: value,
155     };
156
157     if (value.valueSource === ValueSource[ValueSource.Definition]) {
158       if (definition.type === 'object') {
159         node.children = this.getPropertyFromObject(definition, value.value);
160       } else if (definition.type === 'array') {
161         node.children = this.setChildrenForArray(definition, value.value);
162       }
163     }
164
165     return node;
166   }
167
168   private getTreeNodeType(param: any): string {
169     const type = param.type;
170     if (type === 'array') {
171       return 'array';
172     } else if (type === 'object') {
173       if (param.additionalProperties) {
174         return 'map';
175       } else {
176         return 'object';
177       }
178     } else {
179       return 'default';
180     }
181   }
182
183   private setChildrenForArray(definition: any, value: any[]): any[] {
184     const children = [];
185     value.forEach((itemValue, index) => {
186       const itemCopy = WorkflowUtil.deepClone(definition.items);
187       children.push(this.schema2TreeNode(this.swagger, index, itemCopy, itemValue));
188     });
189
190     return children;
191   }
192
193   private getPropertyFromObject(definition: any, value: any): TreeNode[] {
194     if (definition.properties) {
195       return this.getPropertyFromSimpleObject(definition.properties, value, definition.required);
196     } else if (definition.additionalProperties) {
197       return this.getPropertyFromMapOrDictionary(definition.additionalProperties, value);
198     } else {
199       console.log('getPropertyFromObject() return [], param is:' + JSON.stringify(definition));
200       return [];
201     }
202
203   }
204
205   private getPropertyFromSimpleObject(properties: any, objectValue: any, required: string[]): TreeNode[] {
206     const treeNodes: TreeNode[] = [];
207     for (const key in properties) {
208       let property = properties[key];
209       // init required property
210       property.required = false;
211       if (Array.isArray(required)) {
212         for (let index = 0; index < required.length; index++) {
213           if (required[index] === key) {
214             property.required = true;
215             break;
216           }
217         }
218       }
219
220       objectValue[key] = this.getInitValue4Param(property, objectValue[key]);
221
222       const treeNode = this.schema2TreeNode(this.swagger, key, property, objectValue[key]);
223       treeNodes.push(treeNode);
224     }
225     return treeNodes;
226   }
227
228   private getPropertyFromMapOrDictionary(additionalProperties: any, mapOrDictionary: any): TreeNode[] {
229     const treeNodes: TreeNode[] = [];
230     for (const key in mapOrDictionary) {
231       const propertyCopy = WorkflowUtil.deepClone(additionalProperties);
232       propertyCopy.value = mapOrDictionary[key];
233
234       const treeNode = this.schema2TreeNode(this.swagger, key, propertyCopy, propertyCopy.value);
235       treeNode.keyEditable = true;
236       treeNodes.push(treeNode);
237
238       if (mapOrDictionary[key] !== propertyCopy.value) {
239         mapOrDictionary[key] = propertyCopy.value;
240       }
241     }
242     return treeNodes;
243   }
244 }