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
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.
16 * SPDX-License-Identifier: Apache-2.0
17 * ============LICENSE_END=========================================================
20 import {Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges} from '@angular/core';
21 import {ComponentMetadata, PropertyBEModel, PropertyDeclareAPIModel, DerivedFEProperty} 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, PROPERTY_DATA} from "../../../../utils/constants";
33 import {YamlFunctionValidationEvent} from "./yaml-function/yaml-function.component";
34 import {ToscaConcatFunction} from "../../../../models/tosca-concat-function";
35 import {YamlFunction} from "../../../../models/yaml-function";
38 selector: 'tosca-function',
39 templateUrl: './tosca-function.component.html',
40 styleUrls: ['./tosca-function.component.less'],
42 export class ToscaFunctionComponent implements OnInit, OnChanges {
44 @Input() property: PropertyBEModel;
45 @Input() componentInstanceMap: Map<string, InstanceFeDetails> = new Map<string, InstanceFeDetails>();
46 @Input() allowClear: boolean = true;
47 @Input() compositionMap: boolean = false;
48 @Input() compositionMapKey: string = "";
49 @Output() onValidFunction: EventEmitter<ToscaGetFunction> = new EventEmitter<ToscaGetFunction>();
50 @Output() onValidityChange: EventEmitter<ToscaFunctionValidationEvent> = new EventEmitter<ToscaFunctionValidationEvent>();
52 toscaFunctionForm: FormControl = new FormControl(undefined, [Validators.required]);
53 toscaFunctionTypeForm: FormControl = new FormControl(undefined, Validators.required);
54 formGroup: FormGroup = new FormGroup({
55 'toscaFunction': this.toscaFunctionForm,
56 'toscaFunctionType': this.toscaFunctionTypeForm,
59 isLoading: boolean = false;
60 toscaFunction: ToscaFunction;
61 toscaFunctions: Array<string> = [];
63 private isInitialized: boolean = false;
64 private componentMetadata: ComponentMetadata;
66 constructor(private topologyTemplateService: TopologyTemplateService,
67 private workspaceService: WorkspaceService) {
71 this.componentMetadata = this.workspaceService.metadata;
72 this.toscaFunction = this.property.toscaFunction ? this.property.toscaFunction : undefined;
73 this.loadToscaFunctions();
74 this.formGroup.valueChanges.subscribe(() => {
75 if (!this.isInitialized) {
78 this.emitValidityChange();
79 if (this.formGroup.valid) {
80 this.onValidFunction.emit(this.toscaFunctionForm.value);
83 this.initToscaFunction();
84 this.emitValidityChange();
85 this.isInitialized = true;
88 ngOnChanges(changes: SimpleChanges): void {
89 if (changes.property) {
91 this.toscaFunction = this.property.toscaFunction ? this.property.toscaFunction : undefined;
92 this.initToscaFunction();
93 this.loadToscaFunctions();
94 this.emitValidityChange();
98 private validate(): boolean {
99 return (!this.toscaFunctionForm.value && !this.toscaFunctionTypeForm.value) || this.formGroup.valid;
102 private initToscaFunction(): void {
103 if (this.compositionMap && this.property.subPropertyToscaFunctions) {
104 let keyToFind = [this.compositionMapKey];
105 let subPropertyToscaFunction = this.property.subPropertyToscaFunctions.find(subPropertyToscaFunction => this.areEqual(subPropertyToscaFunction.subPropertyPath, keyToFind));
107 if (subPropertyToscaFunction){
108 this.toscaFunction = subPropertyToscaFunction.toscaFunction;
109 this.toscaFunctionForm.setValue(this.toscaFunction);
110 this.toscaFunctionTypeForm.setValue(this.toscaFunction.type);
114 if (this.property instanceof PropertyDeclareAPIModel && this.property.subPropertyToscaFunctions && (<PropertyDeclareAPIModel> this.property).propertiesName){
115 let propertiesPath = (<PropertyDeclareAPIModel> this.property).propertiesName.split("#");
116 if (propertiesPath.length > 1){
118 if (this.property.type == PROPERTY_TYPES.MAP || this.property.type == PROPERTY_TYPES.LIST) {
119 if (this.property.type == PROPERTY_TYPES.LIST && this.property.schemaType == PROPERTY_TYPES.MAP) {
120 keyToFind.push((<DerivedFEProperty>this.property.input).parentMapKey);
122 keyToFind.push((<DerivedFEProperty>this.property.input).mapKey);
123 if (this.property.schemaType != PROPERTY_TYPES.MAP && PROPERTY_DATA.SIMPLE_TYPES.indexOf(this.property.schemaType) === -1) {
124 keyToFind.push(propertiesPath.reverse()[0]);
127 let subPropertyToscaFunction = this.property.subPropertyToscaFunctions.find(subPropertyToscaFunction => this.areEqual(subPropertyToscaFunction.subPropertyPath, keyToFind.length > 0 ? keyToFind : propertiesPath.slice(1)));
129 if (subPropertyToscaFunction){
130 this.toscaFunction = subPropertyToscaFunction.toscaFunction;
131 this.toscaFunctionForm.setValue(this.toscaFunction);
132 this.toscaFunctionTypeForm.setValue(this.toscaFunction.type);
138 if (!this.property.isToscaFunction()) {
141 this.toscaFunctionForm.setValue(this.property.toscaFunction);
142 this.toscaFunctionTypeForm.setValue(this.property.toscaFunction.type);
145 private areEqual(array1: string[], array2: string[]): boolean {
146 return array1.length === array2.length && array1.every(function(value, index) { return value === array2[index]})
149 private loadToscaFunctions(): void {
150 this.toscaFunctions = [];
151 this.toscaFunctions.push(ToscaFunctionType.GET_ATTRIBUTE);
152 this.toscaFunctions.push(ToscaFunctionType.GET_INPUT);
153 this.toscaFunctions.push(ToscaFunctionType.GET_PROPERTY);
154 if (this.property.type === PROPERTY_TYPES.STRING) {
155 this.toscaFunctions.push(ToscaFunctionType.CONCAT);
157 this.toscaFunctions.push(ToscaFunctionType.YAML);
160 private resetForm(): void {
161 this.formGroup.reset();
162 this.toscaFunction = undefined;
165 private isGetPropertySelected(): boolean {
166 return this.formGroup.get('toscaFunctionType').value === ToscaGetFunctionType.GET_PROPERTY;
169 private isGetAttributeSelected(): boolean {
170 return this.formGroup.get('toscaFunctionType').value === ToscaGetFunctionType.GET_ATTRIBUTE;
173 private isGetInputSelected(): boolean {
174 return this.formGroup.get('toscaFunctionType').value === ToscaGetFunctionType.GET_INPUT;
177 isConcatSelected(): boolean {
178 return this.formGroup.get('toscaFunctionType').value === ToscaFunctionType.CONCAT;
181 isGetFunctionSelected(): boolean {
182 return this.isGetInputSelected() || this.isGetPropertySelected() || this.isGetAttributeSelected();
185 isYamlFunctionSelected(): boolean {
186 return this.formGroup.get('toscaFunctionType').value === ToscaFunctionType.YAML;
189 onClearValues(): void {
193 showClearButton(): boolean {
194 return this.allowClear && this.toscaFunctionTypeForm.value;
197 onConcatFunctionValidityChange(validationEvent: ToscaConcatFunctionValidationEvent): void {
198 if (validationEvent.isValid) {
199 this.toscaFunctionForm.setValue(validationEvent.toscaConcatFunction);
201 this.toscaFunctionForm.setValue(undefined);
205 onGetFunctionValidityChange(validationEvent: ToscaGetFunctionValidationEvent): void {
206 if (validationEvent.isValid) {
207 this.toscaFunctionForm.setValue(validationEvent.toscaGetFunction);
209 this.toscaFunctionForm.setValue(undefined);
213 onYamlFunctionValidityChange(validationEvent: YamlFunctionValidationEvent): void {
214 if (validationEvent.isValid) {
215 this.toscaFunctionForm.setValue(validationEvent.value);
217 this.toscaFunctionForm.setValue(undefined);
221 onFunctionTypeChange(): void {
222 this.toscaFunction = undefined;
223 this.toscaFunctionForm.reset();
226 private emitValidityChange(): void {
227 const isValid: boolean = this.validate();
228 this.onValidityChange.emit({
230 toscaFunction: isValid ? this.buildFunctionFromForm() : undefined
234 private buildFunctionFromForm(): ToscaFunction {
235 if (!this.toscaFunctionTypeForm.value) {
238 if (this.isConcatSelected()) {
239 return new ToscaConcatFunction(this.toscaFunctionForm.value);
241 if (this.isGetFunctionSelected()) {
242 return new ToscaGetFunction(this.toscaFunctionForm.value);
244 if (this.isYamlFunctionSelected()) {
245 return new YamlFunction(this.toscaFunctionForm.value);
248 console.error(`Function ${this.toscaFunctionTypeForm.value} not supported`);
252 export class ToscaFunctionValidationEvent {
254 toscaFunction: ToscaFunction;