Support TOSCA functions in sub properties
[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, EventEmitter, Input, OnInit, Output} from '@angular/core';
21 import {ComponentMetadata, PropertyBEModel, PropertyDeclareAPIModel} from 'app/models';
22 import {TopologyTemplateService} from "../../../services/component-services/topology-template.service";
23 import {WorkspaceService} from "../../workspace/workspace.service";
24 import {ToscaGetFunctionType} from "../../../../models/tosca-get-function-type";
25 import {InstanceFeDetails} from "../../../../models/instance-fe-details";
26 import {ToscaGetFunction} from "../../../../models/tosca-get-function";
27 import {FormControl, FormGroup, Validators} from "@angular/forms";
28 import {ToscaFunctionType} from "../../../../models/tosca-function-type.enum";
29 import {ToscaGetFunctionValidationEvent} from "./tosca-get-function/tosca-get-function.component";
30 import {ToscaFunction} from "../../../../models/tosca-function";
31 import {ToscaConcatFunctionValidationEvent} from "./tosca-concat-function/tosca-concat-function.component";
32 import {PROPERTY_TYPES} from "../../../../utils/constants";
33 import {YamlFunctionValidationEvent} from "./yaml-function/yaml-function.component";
34
35 @Component({
36     selector: 'tosca-function',
37     templateUrl: './tosca-function.component.html',
38     styleUrls: ['./tosca-function.component.less'],
39 })
40 export class ToscaFunctionComponent implements OnInit {
41
42     @Input() property: PropertyBEModel;
43     @Input() componentInstanceMap: Map<string, InstanceFeDetails> = new Map<string, InstanceFeDetails>();
44     @Input() allowClear: boolean = true;
45     @Output() onValidFunction: EventEmitter<ToscaGetFunction> = new EventEmitter<ToscaGetFunction>();
46     @Output() onValidityChange: EventEmitter<ToscaFunctionValidationEvent> = new EventEmitter<ToscaFunctionValidationEvent>();
47
48     toscaFunctionForm: FormControl = new FormControl(undefined, [Validators.required]);
49     toscaFunctionTypeForm: FormControl = new FormControl(undefined, Validators.required);
50     formGroup: FormGroup = new FormGroup({
51         'toscaFunction': this.toscaFunctionForm,
52         'toscaFunctionType': this.toscaFunctionTypeForm,
53     });
54
55     isLoading: boolean = false;
56     toscaFunction: ToscaFunction;
57     toscaFunctions: Array<string> = [];
58
59     private isInitialized: boolean = false;
60     private componentMetadata: ComponentMetadata;
61
62     constructor(private topologyTemplateService: TopologyTemplateService,
63                 private workspaceService: WorkspaceService) {
64     }
65
66     ngOnInit(): void {
67         this.componentMetadata = this.workspaceService.metadata;
68         this.toscaFunction = this.property.toscaFunction ? this.property.toscaFunction : undefined;
69         this.loadToscaFunctions();
70         this.formGroup.valueChanges.subscribe(() => {
71             if (!this.isInitialized) {
72                 return;
73             }
74             this.emitValidityChange();
75             if (this.formGroup.valid) {
76                 this.onValidFunction.emit(this.toscaFunctionForm.value);
77             }
78         });
79         this.initToscaFunction();
80         this.emitValidityChange();
81         this.isInitialized = true;
82     }
83
84     private validate() {
85         return (!this.toscaFunctionForm.value && !this.toscaFunctionTypeForm.value) || this.formGroup.valid;
86     }
87
88     private initToscaFunction() {
89             if (this.property instanceof PropertyDeclareAPIModel && this.property.subPropertyToscaFunctions && (<PropertyDeclareAPIModel> this.property).propertiesName){
90                 let propertiesPath = (<PropertyDeclareAPIModel> this.property).propertiesName.split("#");
91             if (propertiesPath.length > 1){
92                     propertiesPath = propertiesPath.slice(1);
93                 let subPropertyToscaFunction = this.property.subPropertyToscaFunctions.find(subPropertyToscaFunction => this.areEqual(subPropertyToscaFunction.subPropertyPath, propertiesPath));
94
95                 if (subPropertyToscaFunction){
96                         this.toscaFunction = subPropertyToscaFunction.toscaFunction;
97                     this.toscaFunctionForm.setValue(this.toscaFunction);
98                     this.toscaFunctionTypeForm.setValue(this.toscaFunction.type);
99                 }
100                 return;
101             }
102         }
103         
104         if (!this.property.isToscaFunction()) {
105             return;
106         }
107         this.toscaFunctionForm.setValue(this.property.toscaFunction);
108         this.toscaFunctionTypeForm.setValue(this.property.toscaFunction.type);
109     }
110
111     private areEqual(array1: string[], array2: string[]): boolean {
112             return array1.length === array2.length && array1.every(function(value, index) { return value === array2[index]})
113     }
114
115     private loadToscaFunctions(): void {
116         this.toscaFunctions.push(ToscaFunctionType.GET_ATTRIBUTE);
117         this.toscaFunctions.push(ToscaFunctionType.GET_INPUT);
118         this.toscaFunctions.push(ToscaFunctionType.GET_PROPERTY);
119         if (this.property.type === PROPERTY_TYPES.STRING) {
120             this.toscaFunctions.push(ToscaFunctionType.CONCAT);
121         }
122         this.toscaFunctions.push(ToscaFunctionType.YAML);
123     }
124
125     private resetForm(): void {
126         this.formGroup.reset();
127         this.toscaFunction = undefined;
128     }
129
130     private isGetPropertySelected(): boolean {
131         return this.formGroup.get('toscaFunctionType').value === ToscaGetFunctionType.GET_PROPERTY;
132     }
133
134     private isGetAttributeSelected(): boolean {
135         return this.formGroup.get('toscaFunctionType').value === ToscaGetFunctionType.GET_ATTRIBUTE;
136     }
137
138     private isGetInputSelected(): boolean {
139         return this.formGroup.get('toscaFunctionType').value === ToscaGetFunctionType.GET_INPUT;
140     }
141
142     isConcatSelected(): boolean {
143         return this.formGroup.get('toscaFunctionType').value === ToscaFunctionType.CONCAT;
144     }
145
146     isGetFunctionSelected(): boolean {
147         return this.isGetInputSelected() || this.isGetPropertySelected() || this.isGetAttributeSelected();
148     }
149
150     isYamlFunctionSelected(): boolean {
151         return this.formGroup.get('toscaFunctionType').value === ToscaFunctionType.YAML;
152     }
153
154     onClearValues() {
155         this.resetForm();
156     }
157
158     showClearButton(): boolean {
159         return this.allowClear && this.toscaFunctionTypeForm.value;
160     }
161
162     onConcatFunctionValidityChange(validationEvent: ToscaConcatFunctionValidationEvent) {
163         if (validationEvent.isValid) {
164             this.toscaFunctionForm.setValue(validationEvent.toscaConcatFunction);
165         } else {
166             this.toscaFunctionForm.setValue(undefined);
167         }
168     }
169
170     onGetFunctionValidityChange(validationEvent: ToscaGetFunctionValidationEvent) {
171         if (validationEvent.isValid) {
172             this.toscaFunctionForm.setValue(validationEvent.toscaGetFunction);
173         } else {
174             this.toscaFunctionForm.setValue(undefined);
175         }
176     }
177
178     onYamlFunctionValidityChange(validationEvent: YamlFunctionValidationEvent) {
179         if (validationEvent.isValid) {
180             this.toscaFunctionForm.setValue(validationEvent.value);
181         } else {
182             this.toscaFunctionForm.setValue(undefined);
183         }
184     }
185
186     private emitValidityChange() {
187         const isValid = this.validate();
188         this.onValidityChange.emit({
189             isValid: isValid,
190             toscaFunction: isValid ? this.toscaFunctionForm.value : undefined
191         });
192     }
193
194 }
195
196 export class ToscaFunctionValidationEvent {
197     isValid: boolean;
198     toscaFunction: ToscaFunction;
199 }