62c5e8a52aa2a887b69fe0ddda56830356a7b2a9
[sdc.git] / catalog-ui / src / app / ng2 / pages / composition / interface-operatons / operation-creator / input-list / input-list.component.ts
1 /*
2  * -
3  *  ============LICENSE_START=======================================================
4  *  Copyright (C) 2022 Nordix Foundation.
5  *  ================================================================================
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *       http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  *
18  *  SPDX-License-Identifier: Apache-2.0
19  *  ============LICENSE_END=========================================================
20  */
21
22 import {Component, EventEmitter, Input, Output} from '@angular/core';
23 import {InputOperationParameter} from "../../../../../../models/interfaceOperation";
24 import {DataTypeModel} from "../../../../../../models/data-types";
25 import {DerivedPropertyType} from "../../../../../../models/properties-inputs/property-be-model";
26 import {SubPropertyToscaFunction} from "../../../../../../models/sub-property-tosca-function";
27 import {PROPERTY_DATA, PROPERTY_TYPES} from "../../../../../../utils/constants";
28 import {InstanceFeDetails} from "../../../../../../models/instance-fe-details";
29 import {ToscaFunction} from "../../../../../../models/tosca-function";
30 import {CustomToscaFunction} from "../../../../../../models/default-custom-functions";
31 import {ToscaFunctionType} from 'app/models/tosca-function-type.enum';
32
33 @Component({
34   selector: 'input-list',
35   templateUrl: './input-list.component.html',
36   styleUrls: ['./input-list.component.less']
37 })
38 export class InputListComponent {
39
40   @Input() set inputs(inputs: Array<InputOperationParameter>) {
41     this._inputs = new Array<InputOperationParameter>();
42     if (inputs) {
43       inputs.forEach(input => {
44         const inputCopy = new InputOperationParameter(input);
45         this.initValue(inputCopy);
46
47         this._inputs.push(inputCopy);
48       });
49     }
50   }
51   @Input() dataTypeMap: Map<string, DataTypeModel>;
52   @Input() isViewOnly: boolean;
53   @Input() title: string;
54   @Input() emptyMessage: string;
55   @Input() showToscaFunctionOption: boolean = false;
56   @Input() allowDeletion: boolean = false;
57   @Input() componentInstanceMap: Map<string, InstanceFeDetails> = new Map();
58   @Input() customToscaFunctions: Array<CustomToscaFunction> = [];
59   @Output('onInputsValidityChange') inputsValidityChangeEvent: EventEmitter<boolean> = new EventEmitter<boolean>();
60   @Output('onValueChange') inputValueChangeEvent: EventEmitter<InputOperationParameter> = new EventEmitter<InputOperationParameter>();
61   @Output('onDelete') inputDeleteEvent: EventEmitter<string> = new EventEmitter<string>();
62
63   _inputs: Array<InputOperationParameter> = [];
64
65   getDataType(type: string): DataTypeModel {
66     return this.dataTypeMap.get(type);
67   }
68
69   private initValue(input: InputOperationParameter): void {
70     if (input.value) {
71       try {
72         input.value = JSON.parse(input.value);
73       } catch (e) {
74         console.debug('Could not parse value', input.value, e);
75       }
76       return;
77     }
78
79     if (input.toscaDefaultValue) {
80       try {
81         input.value = JSON.parse(input.toscaDefaultValue);
82         return;
83       } catch (e) {
84         console.debug('Could not parse value', input.value, e);
85       }
86     }
87
88     if (this.isTypeComplex(input.type) || this.isTypeMap(input.type)) {
89       input.value = {};
90     } else if (this.isTypeList(input.type)) {
91       input.value = [];
92     } else {
93       input.value = undefined;
94     }
95   }
96
97   getType(typeName: string): DerivedPropertyType {
98     if (PROPERTY_DATA.SIMPLE_TYPES.indexOf(typeName) > -1) {
99       return DerivedPropertyType.SIMPLE;
100     } else if (typeName === PROPERTY_TYPES.LIST) {
101       return DerivedPropertyType.LIST;
102     } else if (typeName === PROPERTY_TYPES.MAP) {
103       return DerivedPropertyType.MAP;
104     } else {
105       return DerivedPropertyType.COMPLEX;
106     }
107   }
108
109   isTypeSimple(typeName: string): boolean {
110     return this.getType(typeName) == DerivedPropertyType.SIMPLE;
111   }
112
113   isTypeList(typeName: string): boolean {
114     return this.getType(typeName) == DerivedPropertyType.LIST;
115   }
116
117   isTypeMap(typeName: string): boolean {
118     return this.getType(typeName) == DerivedPropertyType.MAP;
119   }
120
121   isTypeComplex(typeName: string): boolean {
122     return !this.isTypeSimple(typeName) && !this.isTypeList(typeName) && !this.isTypeMap(typeName);
123   }
124
125   onValueChange($event: any) {
126     const inputOperationParameter = this._inputs.find(input => input.name == $event.name);
127     if (!inputOperationParameter.subPropertyToscaFunctions) {
128       inputOperationParameter.subPropertyToscaFunctions = [];
129     }
130     if (inputOperationParameter) {
131       inputOperationParameter.valid = true;
132       if ($event.isToscaFunction) {
133         inputOperationParameter.toscaFunction = $event.value;
134         if (!inputOperationParameter.toscaFunction) {
135           inputOperationParameter.valid = false;
136         }
137       } else if (this.isTypeComplex(inputOperationParameter.type)) {
138         this.setComplexType($event, inputOperationParameter);
139       } else {
140         inputOperationParameter.value = $event.value;
141         inputOperationParameter.toscaFunction = null;
142       }
143     }
144       this.inputsValidityChangeEvent.emit(this._inputs.every(input => input.valid === true));
145       this.inputValueChangeEvent.emit(new InputOperationParameter(inputOperationParameter));
146   }
147
148   private setComplexType ($event, inputOperationParameter): void {
149     Object.keys($event.value).forEach(function (key) {
150       let value = $event.value[key];
151       if (!value || value.length < 1) {
152         return;
153       }
154       let subPropertyToscaFunction = inputOperationParameter.subPropertyToscaFunctions.find(existingSubPropertyToscaFunction => {
155         const prop = existingSubPropertyToscaFunction.subPropertyPath;
156         return prop && [key] && prop.length === [key].length && prop.every(function(value, index) { return value === [key][index]});
157       });
158       let valueKeys = value instanceof Object ? Object.keys(value) : undefined;
159       if (value && value.type && value.type in ToscaFunctionType) {
160         if (!subPropertyToscaFunction){
161           subPropertyToscaFunction = new SubPropertyToscaFunction();
162           inputOperationParameter.subPropertyToscaFunctions.push(subPropertyToscaFunction);
163         }
164         subPropertyToscaFunction.toscaFunction = value;
165         $event.value[key] = (value as ToscaFunction).buildValueObject();
166         let array: string[] = [];
167         array.push(key)
168         subPropertyToscaFunction.subPropertyPath = array;
169       } else if (subPropertyToscaFunction && (!valueKeys || !valueKeys.every(value => value.toUpperCase() in ToscaFunctionType))) {
170         inputOperationParameter.subPropertyToscaFunctions.splice(inputOperationParameter.subPropertyToscaFunctions.indexOf(subPropertyToscaFunction), 1)
171       }
172     });
173 }
174
175   onDelete(inputName: string) {
176     this.inputDeleteEvent.emit(inputName);
177   }
178
179 }