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 {AttributeBEModel, ComponentMetadata, DataTypeModel, PropertyBEModel, PropertyModel, PropertyDeclareAPIModel, DerivedFEProperty} 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, PROPERTY_TYPES} 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 import {PropertySource} from "../../../../../models/property-source";
32 import {InstanceFeDetails} from "../../../../../models/instance-fe-details";
33 import {ToscaGetFunction} from "../../../../../models/tosca-get-function";
34 import {FormControl, FormGroup, Validators} from "@angular/forms";
35 import {ToscaGetFunctionTypeConverter} from "../../../../../models/tosca-get-function-type-converter";
36 import {ResourceType} from "app/utils";
39 selector: 'app-tosca-get-function',
40 templateUrl: './tosca-get-function.component.html',
41 styleUrls: ['./tosca-get-function.component.less']
43 export class ToscaGetFunctionComponent implements OnInit, OnChanges {
45 @Input() property: PropertyBEModel;
46 @Input() overridingType: PROPERTY_TYPES;
47 @Input() toscaGetFunction: ToscaGetFunction;
48 @Input() componentInstanceMap: Map<string, InstanceFeDetails> = new Map<string, InstanceFeDetails>();
49 @Input() functionType: ToscaGetFunctionType;
50 @Input() compositionMap: boolean;
51 @Input() compositionMapKey: string;
52 @Output() onValidFunction: EventEmitter<ToscaGetFunction> = new EventEmitter<ToscaGetFunction>();
53 @Output() onValidityChange: EventEmitter<ToscaGetFunctionValidationEvent> = new EventEmitter<ToscaGetFunctionValidationEvent>();
55 formGroup: FormGroup = new FormGroup({
56 'selectedProperty': new FormControl(undefined, Validators.required),
57 'propertySource': new FormControl(undefined, Validators.required)
60 isLoading: boolean = false;
61 propertyDropdownList: Array<PropertyDropdownValue> = [];
62 propertySourceList: Array<string> = [];
63 instanceNameAndIdMap: Map<string, string> = new Map<string, string>();
64 dropdownValuesLabel: string;
65 dropDownErrorMsg: string;
66 indexListValues:Array<ToscaIndexObject>;
67 parentListTypeFlag : boolean;
69 private isInitialized: boolean = false;
70 private componentMetadata: ComponentMetadata;
72 constructor(private topologyTemplateService: TopologyTemplateService,
73 private workspaceService: WorkspaceService,
74 private propertiesService: PropertiesService,
75 private dataTypeService: DataTypeService,
76 private translateService: TranslateService) {
80 this.componentMetadata = this.workspaceService.metadata;
81 this.indexListValues = [];
82 if (this.property != null) {
83 this.parentListTypeFlag = (this.property.type != PROPERTY_TYPES.LIST && (!this.isComplexType(this.property.type) || (this.isComplexType(this.property.type)
84 && this.property instanceof PropertyDeclareAPIModel && (<PropertyDeclareAPIModel> this.property).input instanceof DerivedFEProperty && this.property.input.type != PROPERTY_TYPES.LIST)));
86 this.formGroup.valueChanges.subscribe(() => {
87 this.formValidation();
89 this.loadPropertySourceDropdown();
90 this.loadPropertyDropdownLabel();
91 this.initToscaGetFunction().subscribe(() => {
92 this.isInitialized = true;
96 ngOnChanges(_changes: SimpleChanges): void {
97 if (!this.isInitialized) {
100 this.isInitialized = false;
102 this.loadPropertySourceDropdown();
103 this.loadPropertyDropdownLabel();
104 this.initToscaGetFunction().subscribe(() => {
105 this.isInitialized = true;
109 private initToscaGetFunction(): Observable<void> {
110 return new Observable(subscriber => {
111 if (!this.toscaGetFunction) {
112 if (this.isGetInput()) {
113 this.setSelfPropertySource();
114 this.loadPropertyDropdown();
119 if (this.toscaGetFunction.propertySource == PropertySource.SELF) {
120 this.propertySource.setValue(PropertySource.SELF);
121 } else if (this.toscaGetFunction.propertySource == PropertySource.INSTANCE) {
123 .setValue(this.propertySourceList.find(source => this.toscaGetFunction.sourceName === source));
125 if (this.propertySource.valid) {
126 this.loadPropertyDropdown(() => {
127 this.selectedProperty
128 .setValue(this.propertyDropdownList.find(property => property.propertyName === this.toscaGetFunction.propertyName));
129 if (this.toscaGetFunction.toscaIndexList && this.toscaGetFunction.toscaIndexList.length > 0) {
130 let tempSelectedProperty : PropertyDropdownValue = this.selectedProperty.value;
131 this.toscaGetFunction.toscaIndexList.forEach((indexValue: string, index) => {
132 let tempIndexFlag = false;
133 let tempNestedFlag = false;
134 let tempIndexValue = "0";
135 let tempIndexProperty = tempSelectedProperty;
136 let subPropertyDropdownList : Array<PropertyDropdownValue> = [];
137 if (!isNaN(Number(indexValue)) || indexValue.toLowerCase() === 'index') {
138 tempIndexFlag = true;
139 tempIndexValue = indexValue;
140 tempSelectedProperty = null;
141 if (this.toscaGetFunction.toscaIndexList[index+1]) {
142 tempNestedFlag = true;
143 if (tempIndexProperty.schemaType != null) {
144 const dataTypeFound: DataTypeModel = this.dataTypeService.getDataTypeByModelAndTypeName(this.componentMetadata.model, tempIndexProperty.schemaType);
145 this.addPropertiesToDropdown(dataTypeFound.properties, subPropertyDropdownList);
146 tempSelectedProperty = subPropertyDropdownList.find(property => property.propertyName === this.toscaGetFunction.toscaIndexList[index+1])
147 if (tempSelectedProperty == null && this.toscaGetFunction.toscaIndexList[index+2]) {
148 tempSelectedProperty = subPropertyDropdownList.find(property => property.propertyName === this.toscaGetFunction.toscaIndexList[index+2])
152 let tempIndexValueMap : ToscaIndexObject = {indexFlag : tempIndexFlag, nestedFlag : tempNestedFlag, indexValue: tempIndexValue, indexProperty: tempSelectedProperty, subPropertyArray: subPropertyDropdownList};
153 this.indexListValues.push(tempIndexValueMap);
165 private buildGetFunctionFromForm() {
166 const toscaGetFunction = new ToscaGetFunction();
167 toscaGetFunction.type = ToscaGetFunctionTypeConverter.convertToToscaFunctionType(this.functionType);
168 toscaGetFunction.functionType = this.functionType;
169 const propertySource = this.propertySource.value;
170 if (this.isPropertySourceSelf()) {
171 toscaGetFunction.propertySource = propertySource
172 toscaGetFunction.sourceName = this.componentMetadata.name;
173 toscaGetFunction.sourceUniqueId = this.componentMetadata.uniqueId;
175 toscaGetFunction.propertySource = PropertySource.INSTANCE;
176 toscaGetFunction.sourceName = propertySource;
177 toscaGetFunction.sourceUniqueId = this.instanceNameAndIdMap.get(propertySource);
180 const selectedProperty: PropertyDropdownValue = this.selectedProperty.value;
181 toscaGetFunction.propertyUniqueId = selectedProperty.propertyId;
182 toscaGetFunction.propertyName = selectedProperty.propertyName;
183 toscaGetFunction.propertyPathFromSource = selectedProperty.propertyPath;
184 if (this.indexListValues.length > 0) {
185 let indexAndProperty : Array<string> = [];
186 this.indexListValues.forEach((indexObject : ToscaIndexObject) => {
187 indexAndProperty.push(indexObject.indexValue);
188 if(indexObject.nestedFlag && indexObject.indexProperty != null) {
189 indexAndProperty.push(...indexObject.indexProperty.propertyPath);
192 toscaGetFunction.toscaIndexList = indexAndProperty;
194 return toscaGetFunction;
197 private loadPropertySourceDropdown(): void {
198 if (this.isGetInput()) {
201 this.propertySourceList = [];
202 this.propertySourceList.push(PropertySource.SELF);
203 this.componentInstanceMap.forEach((value, key) => {
204 const instanceName = value.name;
205 this.instanceNameAndIdMap.set(instanceName, key);
206 if (instanceName !== PropertySource.SELF) {
207 this.addToPropertySource(instanceName);
212 private addToPropertySource(source: string): void {
213 this.propertySourceList.push(source);
214 this.propertySourceList.sort((a, b) => {
215 if (a === PropertySource.SELF) {
217 } else if (b === PropertySource.SELF) {
221 return a.localeCompare(b);
225 private formValidation(): void {
226 if (!this.isInitialized) {
229 let formGroupStatus : boolean = this.formGroup.valid;
230 const selectedProperty: PropertyDropdownValue = this.formGroup.value.selectedProperty;
231 if (selectedProperty != null && selectedProperty.isList && formGroupStatus && this.indexListValues.length > 0) {
232 this.indexListValues.forEach((indexObject : ToscaIndexObject, index) => {
233 if (indexObject.indexValue == '') {
234 formGroupStatus = false;
237 if (indexObject.nestedFlag && indexObject.indexProperty == null) {
238 formGroupStatus = false;
243 this.onValidityChange.emit({
244 isValid: formGroupStatus,
245 toscaGetFunction: this.formGroup.valid ? this.buildGetFunctionFromForm() : undefined
247 if (this.formGroup.valid) {
248 this.onValidFunction.emit(this.buildGetFunctionFromForm());
252 private loadPropertyDropdown(onComplete?: () => any): void {
253 this.loadPropertyDropdownLabel();
254 this.loadPropertyDropdownValues(onComplete);
257 private resetForm(): void {
258 this.formGroup.reset();
261 private loadPropertyDropdownLabel(): void {
262 if (!this.functionType) {
265 if (this.isGetInput()) {
266 this.dropdownValuesLabel = this.translateService.translate('INPUT_DROPDOWN_LABEL');
267 } else if (this.isGetProperty()) {
268 this.dropdownValuesLabel = this.translateService.translate('TOSCA_FUNCTION_PROPERTY_DROPDOWN_LABEL');
269 } else if (this.isGetAttribute()) {
270 this.dropdownValuesLabel = this.translateService.translate('TOSCA_FUNCTION_ATTRIBUTE_DROPDOWN_LABEL');
274 private loadPropertyDropdownValues(onComplete?: () => any): void {
275 if (!this.functionType) {
278 this.resetPropertyDropdown();
279 this.fillPropertyDropdownValues(onComplete);
282 private resetPropertyDropdown(): void {
283 this.dropDownErrorMsg = undefined;
284 this.selectedProperty.reset();
285 this.indexListValues = [];
286 this.propertyDropdownList = [];
289 private fillPropertyDropdownValues(onComplete?: () => any): void {
291 const propertiesObservable: Observable<ComponentGenericResponse> = this.getPropertyObservable();
292 propertiesObservable.subscribe( (response: ComponentGenericResponse) => {
293 const properties: Array<PropertyBEModel | AttributeBEModel> = this.extractProperties(response);
294 if (!properties || properties.length === 0) {
295 const msgCode = this.getNotFoundMsgCode();
296 this.dropDownErrorMsg = this.translateService.translate(msgCode, {type: this.overridingType != undefined ? this.overridingType : this.propertyTypeToString()});
299 this.addPropertiesToDropdown(properties, this.propertyDropdownList);
300 if (this.propertyDropdownList.length == 0) {
301 const msgCode = this.getNotFoundMsgCode();
302 this.dropDownErrorMsg = this.translateService.translate(msgCode, {type: this.overridingType != undefined ? this.overridingType : this.propertyTypeToString()});
305 console.error('An error occurred while loading properties.', error);
315 private getNotFoundMsgCode(): string {
316 if (this.isGetInput()) {
317 return 'TOSCA_FUNCTION_NO_INPUT_FOUND';
319 if (this.isGetAttribute()) {
320 return 'TOSCA_FUNCTION_NO_ATTRIBUTE_FOUND';
322 if (this.isGetProperty()) {
323 return 'TOSCA_FUNCTION_NO_PROPERTY_FOUND';
329 private propertyTypeToString() {
330 if (this.isSubProperty()){
331 if ((this.property instanceof PropertyDeclareAPIModel && (<PropertyDeclareAPIModel> this.property).input instanceof DerivedFEProperty)
332 || this.compositionMap) {
333 if(this.isComplexType(this.property.schemaType)){
334 let mapChildProp : DerivedFEProperty = (<DerivedFEProperty> (<PropertyDeclareAPIModel> this.property).input);
335 let propertySchemaType = mapChildProp.type;
336 if (this.property.type == PROPERTY_TYPES.MAP || propertySchemaType == PROPERTY_TYPES.MAP) {
337 if (mapChildProp.mapKey != '' && mapChildProp.mapKey != null && mapChildProp.schema.property.type != null) {
338 propertySchemaType = mapChildProp.schema.property.type;
341 if ((propertySchemaType == PROPERTY_TYPES.MAP || (propertySchemaType == PROPERTY_TYPES.LIST && mapChildProp.schema.property.type == PROPERTY_TYPES.MAP))
342 && mapChildProp.isChildOfListOrMap) {
343 propertySchemaType = PROPERTY_TYPES.STRING;
345 return propertySchemaType;
347 return this.property.schema.property.type;
350 return this.getType((<PropertyDeclareAPIModel>this.property).propertiesName.split("#").slice(1), this.property.type);
352 if (this.property.schemaType) {
353 return `${this.property.type} of ${this.property.schemaType}`;
355 return this.property.type;
358 private isSubProperty(): boolean{
359 return this.property instanceof PropertyDeclareAPIModel && (<PropertyDeclareAPIModel>this.property).propertiesName && (<PropertyDeclareAPIModel>this.property).propertiesName.length > 1;
362 private extractProperties(componentGenericResponse: ComponentGenericResponse): Array<PropertyBEModel | AttributeBEModel> {
363 if (this.isGetInput()) {
364 return componentGenericResponse.inputs;
366 const instanceId = this.instanceNameAndIdMap.get(this.propertySource.value);
367 if (this.isGetProperty()) {
368 if (this.isPropertySourceSelf()) {
369 return componentGenericResponse.properties;
371 let componentInstanceInput = componentGenericResponse.componentInstances.find(compInst => this.isInput(compInst.originType) && compInst.uniqueId === instanceId);
372 if ( componentInstanceInput) {
373 return this.removeSelectedProperty(componentGenericResponse.componentInstancesInputs[instanceId]);
375 return this.removeSelectedProperty(componentGenericResponse.componentInstancesProperties[instanceId]);
377 if (this.isPropertySourceSelf()) {
378 return [...(componentGenericResponse.attributes || []), ...(componentGenericResponse.properties || [])];
380 return [...(componentGenericResponse.componentInstancesAttributes[instanceId] || []),
381 ...(componentGenericResponse.componentInstancesProperties[instanceId] || [])];
384 private isInput (instanceType:string): boolean {
385 return instanceType === ResourceType.VF || instanceType === ResourceType.PNF || instanceType === ResourceType.CVFC || instanceType === ResourceType.CR;
388 private isPropertySourceSelf() {
389 return this.propertySource.value === PropertySource.SELF;
392 private getPropertyObservable(): Observable<ComponentGenericResponse> {
393 if (this.isGetInput()) {
394 return this.topologyTemplateService.getComponentInputsValues(this.componentMetadata.componentType, this.componentMetadata.uniqueId);
396 if (this.isGetProperty()) {
397 if (this.isPropertySourceSelf()) {
398 return this.topologyTemplateService.findAllComponentProperties(this.componentMetadata.componentType, this.componentMetadata.uniqueId);
400 return this.topologyTemplateService.getComponentInstancesAndInputsAndProperties(this.componentMetadata.componentType, this.componentMetadata.uniqueId);
401 // return this.topologyTemplateService.getComponentInstanceInputsAndProperties(this.componentMetadata.componentType, this.componentMetadata.uniqueId);
403 if (this.isGetAttribute()) {
404 if (this.isPropertySourceSelf()) {
405 return this.topologyTemplateService.findAllComponentAttributesAndProperties(this.componentMetadata.componentType, this.componentMetadata.uniqueId);
407 return this.topologyTemplateService.getComponentInstanceAttributesAndProperties(this.componentMetadata.uniqueId, this.componentMetadata.componentType);
411 private removeSelectedProperty(componentInstanceProperties: PropertyModel[]): PropertyModel[] {
412 if (!componentInstanceProperties) {
415 return componentInstanceProperties.filter(property =>
416 (property.uniqueId !== this.property.uniqueId) ||
417 (property.uniqueId === this.property.uniqueId && property.resourceInstanceUniqueId !== this.property.parentUniqueId)
421 private addPropertyToDropdown(propertyDropdownValue: PropertyDropdownValue, propertyList: Array<PropertyDropdownValue>): void {
422 if (!propertyList.find(prop => prop.propertyName === propertyDropdownValue.propertyName)) {
423 propertyList.push(propertyDropdownValue);
424 propertyList.sort((a, b) => a.propertyLabel.localeCompare(b.propertyLabel));
428 private addPropertiesToDropdown(properties: Array<PropertyBEModel | AttributeBEModel>, propertyList: Array<PropertyDropdownValue>): void {
429 for (const property of properties) {
430 if (this.hasSameType(property)) {
431 this.addPropertyToDropdown({
432 propertyName: property.name,
433 propertyId: property.uniqueId,
434 propertyLabel: property.name,
435 propertyPath: [property.name],
436 isList: property.type === PROPERTY_TYPES.LIST,
437 schemaType: (property.type === PROPERTY_TYPES.LIST && this.isComplexType(property.schema.property.type)) ? property.schema.property.type : null
439 } else if (this.isComplexType(property.type)) {
440 this.fillPropertyDropdownWithMatchingChildProperties(property,propertyList);
445 private fillPropertyDropdownWithMatchingChildProperties(inputProperty: PropertyBEModel | AttributeBEModel, propertyList: Array<PropertyDropdownValue>,
446 parentPropertyList: Array<PropertyBEModel | AttributeBEModel> = []): void {
447 const dataTypeFound: DataTypeModel = this.dataTypeService.getDataTypeByModelAndTypeName(this.componentMetadata.model, inputProperty.type);
448 if (!dataTypeFound || !dataTypeFound.properties) {
451 parentPropertyList.push(inputProperty);
452 dataTypeFound.properties.forEach(dataTypeProperty => {
453 if (this.hasSameType(dataTypeProperty)) {
454 this.addPropertyToDropdown({
455 propertyName: dataTypeProperty.name,
456 propertyId: parentPropertyList[0].uniqueId,
457 propertyLabel: parentPropertyList.map(property => property.name).join('->') + '->' + dataTypeProperty.name,
458 propertyPath: [...parentPropertyList.map(property => property.name), dataTypeProperty.name],
459 isList : dataTypeProperty.type === PROPERTY_TYPES.LIST,
460 schemaType: (dataTypeProperty.type === PROPERTY_TYPES.LIST && this.isComplexType(dataTypeProperty.schema.property.type)) ? dataTypeProperty.schema.property.type : null
462 } else if (this.isComplexType(dataTypeProperty.type)) {
463 this.fillPropertyDropdownWithMatchingChildProperties(dataTypeProperty, propertyList, [...parentPropertyList])
468 private hasSameType(property: PropertyBEModel | AttributeBEModel): boolean {
469 if (this.overridingType != undefined) {
470 return property.type === this.overridingType;
472 if (this.property.type === PROPERTY_TYPES.ANY) {
475 let validPropertyType = (this.parentListTypeFlag && property.type === PROPERTY_TYPES.LIST) ? property.schema.property.type : property.type;
476 if (this.parentListTypeFlag && property.type === PROPERTY_TYPES.LIST && this.isComplexType(validPropertyType)) {
477 let returnFlag : boolean = false;
478 const dataTypeFound: DataTypeModel = this.dataTypeService.getDataTypeByModelAndTypeName(this.componentMetadata.model, validPropertyType);
479 if (dataTypeFound && dataTypeFound.properties) {
480 dataTypeFound.properties.forEach(dataTypeProperty => {
481 if (this.hasSameType(dataTypeProperty)) {
484 if (!returnFlag && this.isComplexType(dataTypeProperty.type)) {
485 const nestedDataTypeFound: DataTypeModel = this.dataTypeService.getDataTypeByModelAndTypeName(this.componentMetadata.model, dataTypeProperty.type);
486 if (nestedDataTypeFound && nestedDataTypeFound.properties) {
487 nestedDataTypeFound.properties.forEach( nestedDateTypeProperty => {
488 if (this.hasSameType(nestedDateTypeProperty)) {
498 if (this.typeHasSchema(this.property.type)) {
499 if ((this.property instanceof PropertyDeclareAPIModel && (<PropertyDeclareAPIModel> this.property).input instanceof DerivedFEProperty) || this.compositionMap) {
500 let childObject : DerivedFEProperty = (<DerivedFEProperty>(<PropertyDeclareAPIModel> this.property).input);
501 let childSchemaType = (this.property != null && this.property.schemaType != null) ? this.property.schemaType : childObject.type;
502 if(this.isComplexType(childSchemaType)){
503 if (childObject.type == PROPERTY_TYPES.MAP && childObject.isChildOfListOrMap) {
504 return validPropertyType === PROPERTY_TYPES.STRING;
506 return validPropertyType === childObject.type;
508 return validPropertyType === this.property.schema.property.type;
511 if (!property.schema || !property.schema.property) {
514 return validPropertyType === this.property.type && this.property.schema.property.type === property.schema.property.type;
516 if ((this.property.schema.property.isDataType || this.isComplexType(this.property.type)) && this.property instanceof PropertyDeclareAPIModel && (<PropertyDeclareAPIModel>this.property).propertiesName){
517 let typeToMatch = (<PropertyDeclareAPIModel> this.property).input.type;
518 let childObject : DerivedFEProperty = (<DerivedFEProperty>(<PropertyDeclareAPIModel> this.property).input);
519 if (childObject.type == PROPERTY_TYPES.MAP && childObject.isChildOfListOrMap) {
520 typeToMatch = PROPERTY_TYPES.STRING;
522 if ((typeToMatch === PROPERTY_TYPES.LIST || typeToMatch === PROPERTY_TYPES.MAP) && (<PropertyDeclareAPIModel> this.property).input.schema.property.type && this.compositionMap && !isNaN(Number(this.compositionMapKey))) {
523 typeToMatch = (<PropertyDeclareAPIModel> this.property).input.schema.property.type;
525 return validPropertyType === typeToMatch;
528 return validPropertyType === this.property.type;
531 private getType(propertyPath:string[], type: string): string {
532 const dataTypeFound: DataTypeModel = this.dataTypeService.getDataTypeByModelAndTypeName(this.componentMetadata.model, type);
533 let nestedProperty = dataTypeFound.properties.find(property => property.name === propertyPath[0]);
534 if (propertyPath.length === 1){
535 return nestedProperty.type;
537 return this.getType(propertyPath.slice(1), nestedProperty.type);
540 private isGetProperty(): boolean {
541 return this.functionType === ToscaGetFunctionType.GET_PROPERTY;
544 private isGetAttribute(): boolean {
545 return this.functionType === ToscaGetFunctionType.GET_ATTRIBUTE;
548 private isGetInput(): boolean {
549 return this.functionType === ToscaGetFunctionType.GET_INPUT;
552 private isComplexType(propertyType: string): boolean {
553 return PROPERTY_DATA.SIMPLE_TYPES.indexOf(propertyType) === -1;
556 private typeHasSchema(propertyType: string): boolean {
557 return PROPERTY_TYPES.MAP === propertyType || PROPERTY_TYPES.LIST === propertyType;
560 private stopLoading(): void {
561 this.isLoading = false;
564 private startLoading(): void {
565 this.isLoading = true;
568 showPropertyDropdown(): boolean {
569 if (this.isGetProperty() || this.isGetAttribute()) {
570 return this.propertySource.valid && !this.isLoading && !this.dropDownErrorMsg;
573 return this.functionType && !this.isLoading && !this.dropDownErrorMsg;
576 onPropertySourceChange(): void {
577 this.selectedProperty.reset();
578 this.indexListValues = [];
579 if (!this.functionType || !this.propertySource.valid) {
582 this.loadPropertyDropdown();
585 onPropertyValueChange(): void {
586 let toscaIndexFlag = false;
587 let nestedToscaFlag = false;
588 this.indexListValues = [];
589 let subPropertyDropdownList : Array<PropertyDropdownValue> = [];
590 const selectedProperty: PropertyDropdownValue = this.selectedProperty.value;
591 if (this.parentListTypeFlag && selectedProperty.isList) {
592 toscaIndexFlag = true;
593 if (selectedProperty.schemaType != null) {
594 nestedToscaFlag = true;
595 const dataTypeFound: DataTypeModel = this.dataTypeService.getDataTypeByModelAndTypeName(this.componentMetadata.model, selectedProperty.schemaType);
596 this.addPropertiesToDropdown(dataTypeFound.properties, subPropertyDropdownList);
599 if (toscaIndexFlag || nestedToscaFlag) {
600 let indexValueMap : ToscaIndexObject = {indexFlag : toscaIndexFlag, nestedFlag : nestedToscaFlag, indexValue: "0", indexProperty: null, subPropertyArray: subPropertyDropdownList};
601 this.indexListValues.push(indexValueMap);
603 this.formValidation();
606 onSubPropertyValueChange(indexObject : ToscaIndexObject, elementIndex: number): void {
607 let toscaIndexFlag = false;
608 let nestedToscaFlag = false;
609 let subPropertyDropdownList : Array<PropertyDropdownValue> = [];
610 let selectedProperty: PropertyDropdownValue = indexObject.indexProperty;
611 if (selectedProperty.isList) {
612 toscaIndexFlag = true;
613 if (selectedProperty.schemaType != null) {
614 nestedToscaFlag = true;
615 const dataTypeFound: DataTypeModel = this.dataTypeService.getDataTypeByModelAndTypeName(this.componentMetadata.model, selectedProperty.schemaType);
616 this.addPropertiesToDropdown(dataTypeFound.properties, subPropertyDropdownList);
619 if (toscaIndexFlag || nestedToscaFlag) {
620 let indexValueMap : ToscaIndexObject = {indexFlag : toscaIndexFlag, nestedFlag : nestedToscaFlag, indexValue: "0", indexProperty: null, subPropertyArray: subPropertyDropdownList};
621 if(!this.indexListValues[elementIndex+1]) {
622 this.indexListValues.push(indexValueMap);
624 this.indexListValues[elementIndex+1] = indexValueMap;
627 if(this.indexListValues[elementIndex+1]) {
628 this.indexListValues.splice((elementIndex+1),1);
631 this.formValidation();
634 indexTokenChange(indexObject : ToscaIndexObject): void {
635 if ((indexObject.indexValue).toLowerCase() === 'index' ) {
636 this.formValidation();
639 const regEx = /^[0-9]*$/;
640 const error = document.getElementById('error');
642 if (!(regEx.test(indexObject.indexValue)) && (indexObject.indexValue).toLowerCase() !== 'index') {
643 error.textContent='Invalid value - must be an integer or INDEX';
644 this.onValidityChange.emit({
646 toscaGetFunction: this.formGroup.valid ? this.buildGetFunctionFromForm() : undefined
649 error.textContent='';
650 this.formValidation();
654 showPropertySourceDropdown(): boolean {
655 return this.isGetProperty() || this.isGetAttribute();
658 private setSelfPropertySource(): void {
659 this.propertySource.setValue(PropertySource.SELF);
662 private get propertySource(): FormControl {
663 return this.formGroup.get('propertySource') as FormControl;
666 private get selectedProperty(): FormControl {
667 return this.formGroup.get('selectedProperty') as FormControl;
670 onChangeIndexValue(index: ToscaIndexObject, value: any) {
671 this.indexTokenChange(index);
675 export interface PropertyDropdownValue {
676 propertyName: string;
678 propertyLabel: string;
679 propertyPath: Array<string>;
684 export interface ToscaIndexObject {
688 indexProperty: PropertyDropdownValue;
689 subPropertyArray: Array<PropertyDropdownValue>;
692 export interface ToscaGetFunctionValidationEvent {
694 toscaGetFunction: ToscaGetFunction,