Support of get_property in property assignment
[sdc.git] / catalog-ui / src / app / ng2 / pages / properties-assignment / tosca-function / tosca-function.component.ts
1 /*
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2021 Nordix Foundation
4  *  ================================================================================
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License.
15  *
16  *  SPDX-License-Identifier: Apache-2.0
17  *  ============LICENSE_END=========================================================
18  */
19
20 import {Component, Input} from '@angular/core';
21 import {ComponentMetadata, DataTypeModel, PropertyBEModel} from 'app/models';
22 import {TopologyTemplateService} from "../../../services/component-services/topology-template.service";
23 import {WorkspaceService} from "../../workspace/workspace.service";
24 import {PropertiesService} from "../../../services/properties.service";
25 import {PROPERTY_DATA} from "../../../../utils/constants";
26 import {DataTypeService} from "../../../services/data-type.service";
27 import {ToscaGetFunctionType} from "../../../../models/tosca-get-function-type";
28 import {TranslateService} from "../../../shared/translator/translate.service";
29 import {ComponentGenericResponse} from '../../../services/responses/component-generic-response';
30 import {Observable} from 'rxjs/Observable';
31
32 @Component({
33     selector: 'tosca-function',
34     templateUrl: './tosca-function.component.html',
35     styleUrls: ['./tosca-function.component.less'],
36 })
37 export class ToscaFunctionComponent {
38
39     @Input() property: PropertyBEModel;
40
41     selectToscaFunction;
42     selectedProperty: PropertyDropdownValue;
43     isLoading: boolean = false;
44     propertyDropdownList: Array<PropertyDropdownValue> = [];
45     toscaFunctions: Array<string> = [];
46     dropdownValuesLabel: string;
47     dropDownErrorMsg: string;
48
49     private componentMetadata: ComponentMetadata;
50
51     constructor(private topologyTemplateService: TopologyTemplateService,
52                 private workspaceService: WorkspaceService,
53                 private propertiesService: PropertiesService,
54                 private dataTypeService: DataTypeService,
55                 private translateService: TranslateService) {
56     }
57
58     ngOnInit() {
59         this.componentMetadata = this.workspaceService.metadata;
60         this.loadToscaFunctions();
61     }
62
63     private loadToscaFunctions(): void {
64         this.toscaFunctions.push(ToscaGetFunctionType.GET_INPUT.toLowerCase());
65         this.toscaFunctions.push(ToscaGetFunctionType.GET_PROPERTY.toLowerCase());
66     }
67
68     onToscaFunctionChange(): void {
69         this.loadDropdownValueLabel();
70         this.loadDropdownValues();
71     }
72
73     private loadDropdownValueLabel(): void {
74         if (!this.selectToscaFunction) {
75             return;
76         }
77         if (this.isGetInputSelected()) {
78             this.dropdownValuesLabel = this.translateService.translate('INPUT_DROPDOWN_LABEL');
79         } else if (this.isGetPropertySelected()) {
80             this.dropdownValuesLabel = this.translateService.translate('TOSCA_FUNCTION_PROPERTY_DROPDOWN_LABEL');
81         }
82     }
83
84     private loadDropdownValues(): void {
85         if (!this.selectToscaFunction) {
86             return;
87         }
88         this.resetDropDown();
89         this.loadPropertiesInDropdown();
90     }
91
92     private resetDropDown() {
93         this.dropDownErrorMsg = undefined;
94         this.propertyDropdownList = [];
95     }
96
97     private loadPropertiesInDropdown() {
98         this.startLoading();
99         let propertiesObservable: Observable<ComponentGenericResponse>
100         if (this.isGetInputSelected()) {
101             propertiesObservable = this.topologyTemplateService.getComponentInputsValues(this.componentMetadata.componentType, this.componentMetadata.uniqueId);
102         } else if (this.isGetPropertySelected()) {
103             propertiesObservable = this.topologyTemplateService.findAllComponentProperties(this.componentMetadata.componentType, this.componentMetadata.uniqueId);
104         }
105         propertiesObservable
106             .subscribe( (response: ComponentGenericResponse) => {
107                 let properties: PropertyBEModel[] = this.isGetInputSelected() ? response.inputs : response.properties;
108                 if (!properties || properties.length === 0) {
109                     const msgCode = this.isGetInputSelected() ? 'TOSCA_FUNCTION_NO_INPUT_FOUND' : 'TOSCA_FUNCTION_NO_PROPERTY_FOUND';
110                     this.dropDownErrorMsg = this.translateService.translate(msgCode, {type: this.property.type});
111                     return;
112                 }
113                 this.addPropertiesToDropdown(properties);
114                 if (this.propertyDropdownList.length == 0) {
115                     const msgCode = this.isGetInputSelected() ? 'TOSCA_FUNCTION_NO_INPUT_FOUND' : 'TOSCA_FUNCTION_NO_PROPERTY_FOUND';
116                     this.dropDownErrorMsg = this.translateService.translate(msgCode, {type: this.property.type});
117                 }
118             }, (error) => {
119                 console.error('An error occurred while loading properties.', error);
120             }, () => {
121                 this.stopLoading();
122             });
123     }
124
125     private addPropertyToDropdown(propertyDropdownValue: PropertyDropdownValue) {
126         this.propertyDropdownList.push(propertyDropdownValue);
127         this.propertyDropdownList.sort((a, b) => a.propertyLabel.localeCompare(b.propertyLabel));
128     }
129
130     private addPropertiesToDropdown(properties: PropertyBEModel[]) {
131         for (const property of properties) {
132             if (this.property.type === property.type) {
133                 this.addPropertyToDropdown({
134                     propertyName: property.name,
135                     propertyId: property.uniqueId,
136                     propertyLabel: property.name,
137                     toscaFunction: this.selectToscaFunction,
138                     propertyPath: [property.name]
139                 });
140             } else if (this.isComplexType(property.type)) {
141                 this.fillPropertyDropdownWithMatchingChildProperties(property);
142             }
143         }
144     }
145
146     private fillPropertyDropdownWithMatchingChildProperties(inputProperty: PropertyBEModel, parentPropertyList: Array<PropertyBEModel> = []) {
147         const dataTypeFound: DataTypeModel = this.dataTypeService.getDataTypeByModelAndTypeName(this.componentMetadata.model, inputProperty.type);
148         if (!dataTypeFound || !dataTypeFound.properties) {
149             return;
150         }
151         parentPropertyList.push(inputProperty);
152         dataTypeFound.properties.forEach(dataTypeProperty => {
153             if (dataTypeProperty.type === this.property.type) {
154                 this.addPropertyToDropdown({
155                     propertyName: dataTypeProperty.name,
156                     propertyId: parentPropertyList[0].uniqueId,
157                     propertyLabel: parentPropertyList.map(property => property.name).join('->') + '->' + dataTypeProperty.name,
158                     toscaFunction: this.selectToscaFunction,
159                     propertyPath: [...parentPropertyList.map(property => property.name), dataTypeProperty.name]
160                 });
161             } else if (PROPERTY_DATA.SIMPLE_TYPES.indexOf(dataTypeProperty.type) === -1) {
162                 this.fillPropertyDropdownWithMatchingChildProperties(dataTypeProperty, [...parentPropertyList])
163             }
164         });
165     }
166
167     private isGetPropertySelected() {
168         return this.selectToscaFunction === ToscaGetFunctionType.GET_PROPERTY.toLowerCase();
169     }
170
171     private isGetInputSelected() {
172         return this.selectToscaFunction === ToscaGetFunctionType.GET_INPUT.toLowerCase();
173     }
174
175     private isComplexType(propertyType: string) {
176         return PROPERTY_DATA.SIMPLE_TYPES.indexOf(propertyType) === -1;
177     }
178
179     private stopLoading() {
180         this.isLoading = false;
181     }
182
183     private startLoading() {
184         this.isLoading = true;
185     }
186
187     showDropdown(): boolean {
188         return this.selectToscaFunction && !this.isLoading && !this.dropDownErrorMsg;
189     }
190
191 }
192
193 export interface PropertyDropdownValue {
194     propertyName: string;
195     propertyId: string;
196     propertyLabel: string;
197     toscaFunction: ToscaGetFunctionType;
198     propertyPath: Array<string>;
199 }