f8a2160374daf2c6b4b7f3271e5bd29d1cb0d0b7
[sdc.git] / catalog-ui / src / app / ng2 / pages / service-dependencies-editor / service-dependencies-editor.component.ts
1 /*!
2  * Copyright © 2016-2018 European Support Limited
3  * Modification Copyright (C) 2022 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  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
14  * or implied. See the License for the specific language governing
15  * permissions and limitations under the License.
16  */
17 import {Component, Input, OnInit} from '@angular/core';
18 import {InputBEModel, PropertyBEModel, PropertyFEModel, PropertyModel} from 'app/models';
19 import {SourceType} from 'app/ng2/components/logic/service-dependencies/service-dependencies.component';
20 import {DropdownValue} from 'app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component';
21 import {ServiceServiceNg2} from 'app/ng2/services/component-services/service.service';
22 import {PROPERTY_DATA} from 'app/utils';
23 import {PropertiesUtils} from '../properties-assignment/services/properties.utils';
24 import {ToscaFunctionValidationEvent} from "../properties-assignment/tosca-function/tosca-function.component";
25 import {InstanceFeDetails} from "../../../models/instance-fe-details";
26 import {CompositionService} from "../composition/composition.service";
27 import {ToscaGetFunction} from "../../../models/tosca-get-function";
28 import {PropertyFilterConstraintUi} from "../../../models/ui-models/property-filter-constraint-ui";
29 import {ConstraintOperatorType, FilterConstraintHelper} from "../../../utils/filter-constraint-helper";
30 import {ToscaFunctionHelper} from "../../../utils/tosca-function-helper";
31
32 @Component({
33   selector: 'service-dependencies-editor',
34   templateUrl: './service-dependencies-editor.component.html',
35   styleUrls: ['./service-dependencies-editor.component.less'],
36   providers: [ServiceServiceNg2]
37 })
38 export class ServiceDependenciesEditorComponent implements OnInit {
39
40   @Input() serviceRuleIndex: number;
41   @Input() serviceRules: PropertyFilterConstraintUi[];
42   @Input() compositeServiceName: string;
43   @Input() currentServiceName: string;
44   @Input() parentServiceInputs: InputBEModel[];
45   @Input() parentServiceProperties: PropertyBEModel[];
46   @Input() selectedInstanceProperties: PropertyBEModel[];
47   @Input() allowedOperators: ConstraintOperatorType[] = [
48       ConstraintOperatorType.GREATER_THAN,
49       ConstraintOperatorType.LESS_THAN,
50       ConstraintOperatorType.EQUAL,
51       ConstraintOperatorType.GREATER_OR_EQUAL,
52       ConstraintOperatorType.LESS_OR_EQUAL
53   ];
54   @Input() capabilityNameAndPropertiesMap: Map<string, PropertyModel[]>;
55   @Input() filterType: FilterType;
56   @Input() filterConstraint: PropertyFilterConstraintUi;
57   //output
58   currentRule: PropertyFilterConstraintUi;
59
60   FILTER_TYPE_CAPABILITY: FilterType = FilterType.CAPABILITY
61
62   operatorTypes: DropdownValue[] = [
63     {label: FilterConstraintHelper.convertToSymbol(ConstraintOperatorType.GREATER_THAN), value: ConstraintOperatorType.GREATER_THAN},
64     {label: FilterConstraintHelper.convertToSymbol(ConstraintOperatorType.LESS_THAN), value: ConstraintOperatorType.LESS_THAN},
65     {label: FilterConstraintHelper.convertToSymbol(ConstraintOperatorType.EQUAL), value: ConstraintOperatorType.EQUAL},
66     {label: FilterConstraintHelper.convertToSymbol(ConstraintOperatorType.GREATER_OR_EQUAL), value: ConstraintOperatorType.GREATER_OR_EQUAL},
67     {label: FilterConstraintHelper.convertToSymbol(ConstraintOperatorType.LESS_OR_EQUAL), value: ConstraintOperatorType.LESS_OR_EQUAL}
68   ];
69
70   servicePropertyDropdownList: DropdownValue[];
71   isLoading: false;
72   selectedProperty: PropertyFEModel;
73   selectedSourceType: string;
74   componentInstanceMap: Map<string, InstanceFeDetails> = new Map<string, InstanceFeDetails>();
75   capabilityDropdownList: DropdownValue[] = [];
76
77   SOURCE_TYPES = {
78     STATIC: {label: 'Static', value: SourceType.STATIC},
79     TOSCA_FUNCTION: {label: 'Tosca Function', value: SourceType.TOSCA_FUNCTION}
80   };
81
82   constructor(private propertiesUtils: PropertiesUtils, private compositionService: CompositionService) {}
83
84   ngOnInit(): void {
85     if (this.compositionService.componentInstances) {
86       this.compositionService.componentInstances.forEach(value => {
87         this.componentInstanceMap.set(value.uniqueId, <InstanceFeDetails>{
88           name: value.name
89         });
90       });
91     }
92     this.initCapabilityDropdown();
93     this.initCurrentRule();
94     this.initConstraintOperatorOptions();
95     this.initSelectedSourceType();
96     this.initPropertyDropdown();
97     this.syncRuleData();
98   }
99
100
101   private initCapabilityDropdown(): void {
102     if (this.filterType == FilterType.CAPABILITY) {
103       this.capabilityDropdownList = [
104         new DropdownValue(undefined, 'Select'),
105         ...Array.from(this.capabilityNameAndPropertiesMap.keys()).map(capabilityName => new DropdownValue(capabilityName, capabilityName))
106       ];
107     }
108   }
109
110   private initPropertyDropdown(): void {
111     let propertyList: PropertyBEModel[] = [];
112     if (this.filterType == FilterType.CAPABILITY) {
113       if (this.currentRule.capabilityName) {
114         propertyList = this.capabilityNameAndPropertiesMap.get(this.currentRule.capabilityName);
115       }
116     } else {
117       propertyList = this.selectedInstanceProperties;
118     }
119     let selectLabel;
120     if (this.filterType == FilterType.CAPABILITY) {
121       selectLabel = this.currentRule.capabilityName ? 'Select' : 'Select a Capability';
122     } else {
123       selectLabel = 'Select';
124     }
125     this.servicePropertyDropdownList = [new DropdownValue(undefined, selectLabel), ...propertyList.map(prop => new DropdownValue(prop.name, prop.name))];
126   }
127
128   private initConstraintOperatorOptions(): void {
129     if (!this.selectedProperty) {
130       this.operatorTypes = [new DropdownValue(undefined, 'Select a Property')];
131       return;
132     }
133
134     if (PROPERTY_DATA.SIMPLE_TYPES_COMPARABLE.indexOf(this.selectedProperty.type) === -1) {
135       if (this.currentRule.constraintOperator !== ConstraintOperatorType.EQUAL) {
136         this.currentRule.constraintOperator = ConstraintOperatorType.EQUAL;
137       }
138       this.operatorTypes = [new DropdownValue(ConstraintOperatorType.EQUAL, FilterConstraintHelper.convertToSymbol(ConstraintOperatorType.EQUAL))];
139     } else {
140       const operatorList: DropdownValue[] = [];
141       this.allowedOperators.forEach(constraintOperatorType =>
142         operatorList.push(new DropdownValue(constraintOperatorType, FilterConstraintHelper.convertToSymbol(constraintOperatorType)))
143       );
144       this.operatorTypes = operatorList;
145     }
146   }
147
148   private initSelectedSourceType(): void {
149     if (!this.currentRule.sourceType || this.currentRule.sourceType === SourceType.STATIC) {
150       this.selectedSourceType = SourceType.STATIC;
151     } else {
152       this.selectedSourceType = SourceType.TOSCA_FUNCTION;
153     }
154   }
155
156   private initCurrentRule(): void {
157     if (this.filterConstraint) {
158       this.currentRule = new PropertyFilterConstraintUi(this.filterConstraint);
159     } else {
160       this.currentRule = new PropertyFilterConstraintUi({
161         sourceName: SourceType.STATIC,
162         sourceType: SourceType.STATIC,
163         constraintOperator: ConstraintOperatorType.EQUAL,
164         value: undefined
165       });
166     }
167   }
168
169   onCapabilityChange(): void {
170     this.initPropertyDropdown();
171     this.resetSelectedProperty();
172   }
173
174   onPropertyChange(): void {
175     this.currentRule.sourceName = undefined;
176     this.currentRule.value = undefined;
177     this.onValueChange(false);
178     this.updateSelectedProperty();
179     this.initConstraintOperatorOptions();
180   }
181
182   syncRuleData(): void {
183     if (!this.currentRule.sourceName || this.currentRule.sourceType === SourceType.STATIC) {
184       this.currentRule.sourceName = SourceType.STATIC;
185       this.currentRule.sourceType = SourceType.STATIC;
186     }
187     this.initSelectedProperty();
188     this.initConstraintOperatorOptions();
189   }
190
191   onValueChange(isValidValue:any): void {
192     this.currentRule.updateValidity(isValidValue);
193   }
194
195   checkFormValidForSubmit(): boolean {
196     return this.currentRule.isValidRule();
197   }
198
199   initSelectedProperty(): void {
200     if (!this.currentRule.servicePropertyName) {
201       this.selectedProperty = undefined;
202       return;
203     }
204     let newProperty;
205     if (this.filterType === FilterType.CAPABILITY) {
206       const currentProperty = this.capabilityNameAndPropertiesMap.get(this.currentRule.capabilityName)
207         .find(property => property.name === this.currentRule.servicePropertyName);
208       newProperty = new PropertyFEModel(currentProperty);
209     } else {
210       newProperty = new PropertyFEModel(this.selectedInstanceProperties.find(property => property.name === this.currentRule.servicePropertyName));
211     }
212     newProperty.value = undefined;
213     newProperty.toscaFunction = undefined;
214     if (typeof this.currentRule.value === 'string') {
215       newProperty.value = this.currentRule.value;
216       this.propertiesUtils.initValueObjectRef(newProperty);
217     } else if (ToscaFunctionHelper.isValueToscaFunction(this.currentRule.value)) {
218       newProperty.toscaFunction = ToscaFunctionHelper.convertObjectToToscaFunction(this.currentRule.value);
219       newProperty.value = newProperty.toscaFunction.buildValueString();
220     } else {
221       newProperty.value = JSON.stringify(this.currentRule.value);
222       this.propertiesUtils.initValueObjectRef(newProperty);
223     }
224
225     this.selectedProperty = newProperty;
226   }
227
228   updateSelectedProperty(): void {
229     this.selectedProperty = undefined;
230     if (!this.currentRule.servicePropertyName) {
231       return;
232     }
233
234     let newProperty;
235     if (this.filterType === FilterType.CAPABILITY) {
236       const currentProperty = this.capabilityNameAndPropertiesMap.get(this.currentRule.capabilityName)
237         .find(property => property.name === this.currentRule.servicePropertyName);
238       newProperty = new PropertyFEModel(currentProperty);
239     } else {
240       newProperty = new PropertyFEModel(this.selectedInstanceProperties.find(property => property.name === this.currentRule.servicePropertyName));
241     }
242     newProperty.value = undefined;
243     newProperty.toscaFunction = undefined;
244
245     this.propertiesUtils.initValueObjectRef(newProperty);
246     this.selectedProperty = newProperty;
247   }
248
249   isStaticSource(): boolean {
250     return this.selectedSourceType === SourceType.STATIC
251   }
252
253   isToscaFunctionSource(): boolean {
254     return this.selectedSourceType === SourceType.TOSCA_FUNCTION
255   }
256
257   isComplexListMapType(): boolean {
258     return this.selectedProperty && this.selectedProperty.derivedDataType > 0;
259   }
260
261   updateComplexListMapTypeRuleValue(): void {
262     this.currentRule.value = PropertyFEModel.cleanValueObj(this.selectedProperty.valueObj);
263     this.onValueChange(this.selectedProperty.valueObjIsValid);
264   }
265
266   onToscaFunctionValidityChange(validationEvent: ToscaFunctionValidationEvent): void {
267     if (validationEvent.isValid && validationEvent.toscaFunction) {
268       this.currentRule.value = validationEvent.toscaFunction;
269       this.currentRule.sourceType = validationEvent.toscaFunction.type
270       if (validationEvent.toscaFunction instanceof ToscaGetFunction) {
271         this.currentRule.sourceName = validationEvent.toscaFunction.sourceName;
272       }
273     } else {
274       this.currentRule.updateValidity(false);
275       this.currentRule.value = undefined;
276       this.currentRule.sourceType = undefined;
277       this.currentRule.sourceName = undefined;
278     }
279   }
280
281   onSourceTypeChange(): void {
282     this.currentRule.value = undefined;
283     this.currentRule.sourceType = this.selectedSourceType;
284     if (this.isStaticSource()) {
285       this.currentRule.sourceName = SourceType.STATIC;
286     }
287     this.updateSelectedProperty();
288   }
289
290   private resetSelectedProperty(): void {
291     this.currentRule.servicePropertyName = undefined;
292     this.selectedProperty = undefined;
293     this.onPropertyChange();
294   }
295
296 }
297
298 export enum FilterType {
299   CAPABILITY,
300   PROPERTY
301 }