diff options
author | andre.schmid <andre.schmid@est.tech> | 2022-05-27 11:58:10 +0100 |
---|---|---|
committer | Michael Morris <michael.morris@est.tech> | 2022-06-02 13:38:18 +0000 |
commit | e159dee791441b68d142323f7d951b0592841c7f (patch) | |
tree | 246064e0cc3151f7b2604cb77531fcc6d4394fbb | |
parent | 27cbc536b9a8f10e32b2189effc5466cbe571701 (diff) |
Support of get_property for instance properties
Support of get_property for INSTANCE properties, as currently only
SELF properties can be selected.
Change-Id: I80611002964a6ebb515134155c321f2d7f87811c
Issue-ID: SDC-4026
Signed-off-by: andre.schmid <andre.schmid@est.tech>
14 files changed, 305 insertions, 68 deletions
diff --git a/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml b/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml index 99abb7b1ab..53f7c1d41a 100644 --- a/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml +++ b/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml @@ -2717,3 +2717,11 @@ errors: messageId: "SVC4170" } + #---------SVC4171----------------------------- + # %1 - Instance name + TOSCA_GET_FUNCTION_INSTANCE_NOT_FOUND: { + code: 404, + message: "The instance '%1' was not found.", + messageId: "SVC4171" + } + diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java index 1fa459da80..7ea00b1d46 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java @@ -2374,12 +2374,21 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { private <T extends PropertyDefinition> void validateToscaGetFunction(T property, Component parentComponent) { final ToscaGetFunctionDataDefinition toscaGetFunction = property.getToscaGetFunction(); + validateGetPropertySource(toscaGetFunction.getFunctionType(), toscaGetFunction.getPropertySource()); if (toscaGetFunction.getFunctionType() == ToscaGetFunctionType.GET_INPUT) { validateGetFunction(property, parentComponent.getInputs(), parentComponent.getModel()); return; } if (toscaGetFunction.getFunctionType() == ToscaGetFunctionType.GET_PROPERTY) { - validateGetFunction(property, parentComponent.getProperties(), parentComponent.getModel()); + if (toscaGetFunction.getPropertySource() == PropertySource.SELF) { + validateGetFunction(property, parentComponent.getProperties(), parentComponent.getModel()); + } else if (toscaGetFunction.getPropertySource() == PropertySource.INSTANCE) { + final ComponentInstance componentInstance = + parentComponent.getComponentInstanceById(toscaGetFunction.getSourceUniqueId()) + .orElseThrow(ToscaGetFunctionExceptionSupplier.instanceNotFound(toscaGetFunction.getSourceName())); + validateGetFunction(property, componentInstance.getProperties(), parentComponent.getModel()); + } + return; } @@ -2396,7 +2405,6 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { toscaGetFunction.getFunctionType() ).get(); } - validateGetPropertySource(toscaGetFunction.getFunctionType(), toscaGetFunction.getPropertySource()); final String getFunctionPropertyUniqueId = toscaGetFunction.getPropertyUniqueId(); T referredProperty = (T) parentProperties.stream() .filter(property1 -> getFunctionPropertyUniqueId.equals(property1.getUniqueId())) @@ -2458,7 +2466,11 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { } private void validateGetPropertySource(final ToscaGetFunctionType functionType, final PropertySource propertySource) { - if (propertySource != PropertySource.SELF) { + if (functionType == ToscaGetFunctionType.GET_INPUT && propertySource != PropertySource.SELF) { + throw ToscaGetFunctionExceptionSupplier + .targetSourceNotSupported(functionType, propertySource).get(); + } + if (functionType == ToscaGetFunctionType.GET_PROPERTY && !List.of(PropertySource.SELF, PropertySource.INSTANCE).contains(propertySource)) { throw ToscaGetFunctionExceptionSupplier .targetSourceNotSupported(functionType, propertySource).get(); } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/exceptions/ToscaGetFunctionExceptionSupplier.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/exceptions/ToscaGetFunctionExceptionSupplier.java index d54cb79ba5..5e1d005bfa 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/exceptions/ToscaGetFunctionExceptionSupplier.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/exceptions/ToscaGetFunctionExceptionSupplier.java @@ -91,4 +91,12 @@ public class ToscaGetFunctionExceptionSupplier { functionType.getFunctionName(), referredPropertySchemaType, propertySchemaType ); } + + public static Supplier<ByActionStatusComponentException> instanceNotFound(final String instanceName) { + return () -> new ByActionStatusComponentException( + ActionStatus.TOSCA_GET_FUNCTION_INSTANCE_NOT_FOUND, + instanceName + ); + } + } diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogicTest.java index c0ad54c699..c7d66bf80f 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogicTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogicTest.java @@ -396,7 +396,7 @@ class ComponentInstanceBusinessLogicTest { getPropertyPropertyName, mapToscaType, "string", - String.format("get_property: [\"%s\"]", String.join(",", containerPropertyPath)), + String.format("\"get_property\": [\"%s\", \"%s\"]", PropertySource.SELF, String.join("\", \"", containerPropertyPath)), createGetToscaFunction(containerPropertyPath.get(containerPropertyPath.size() - 1), containerPropertyId, containerPropertyPath, PropertySource.SELF, ToscaGetFunctionType.GET_PROPERTY, containerComponentId, containerComponentName) ); @@ -458,6 +458,60 @@ class ComponentInstanceBusinessLogicTest { assertThat(actualResponseFormat.left().value()).isEqualTo(resourceInstanceProperties); } + @Test + void testToscaGetPropertyOnInstanceValidation() { + final String userId = "userId"; + final String containerComponentId = "containerComponentId"; + final String containerComponentName = "containerComponentName"; + final String instanceUniqueId = String.format("%s.%s", containerComponentId, "instanceId"); + + final List<String> parentPropertyPath = List.of("property1"); + final String containerPropertyId = String.format("%s.%s", containerComponentId, parentPropertyPath.get(0)); + final ComponentInstanceProperty getPropertyOnInstanceProperty = createComponentInstanceProperty( + String.format("%s.%s", containerComponentId, "getPropertyOnInstanceProperty"), + "getPropertyOnInstanceProperty", + "string", + null, + String.format("\"get_property\": [\"%s\", \"%s\"]", PropertySource.INSTANCE, parentPropertyPath.get(0)), + createGetToscaFunction(parentPropertyPath.get(0), containerPropertyId, parentPropertyPath, PropertySource.INSTANCE, + ToscaGetFunctionType.GET_PROPERTY, instanceUniqueId, containerComponentName) + ); + + //creating component that has the instance properties + final Component component = new Service(); + component.setUniqueId(containerComponentId); + component.setName(containerComponentName); + component.setLastUpdaterUserId(userId); + component.setLifecycleState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT); + //adding instance properties to the component + final List<ComponentInstanceProperty> resourceInstanceProperties = List.of(getPropertyOnInstanceProperty); + final Map<String, List<ComponentInstanceProperty>> componentInstanceProps = new HashMap<>(); + componentInstanceProps.put(instanceUniqueId, resourceInstanceProperties); + component.setComponentInstancesProperties(componentInstanceProps); + + //creating resource property that will be get + final var propertyDefinition = new PropertyDefinition(); + propertyDefinition.setName(parentPropertyPath.get(0)); + propertyDefinition.setUniqueId(containerPropertyId); + final String property1Type = "string"; + propertyDefinition.setType(property1Type); + //creating resource instance to be added to the component + final ComponentInstance resourceInstance = createComponentInstance("resourceInstance"); + resourceInstance.setUniqueId(instanceUniqueId); + resourceInstance.setProperties(List.of(propertyDefinition)); + component.setComponentInstances(List.of(resourceInstance)); + + mockComponentForToscaGetFunctionValidation(component); + + //when + final Either<List<ComponentInstanceProperty>, ResponseFormat> actualResponseFormat = componentInstanceBusinessLogic + .createOrUpdatePropertiesValues( + ComponentTypeEnum.RESOURCE_INSTANCE, containerComponentId, instanceUniqueId, resourceInstanceProperties, userId); + //then + assertTrue(actualResponseFormat.isLeft()); + assertThat(actualResponseFormat.left().value()).isEqualTo(resourceInstanceProperties); + } + private DataTypeDefinition createDataType(final String name, final Map<String, String> propertyNameAndTypeMap) { final var dataTypeDefinition = new DataTypeDefinition(); dataTypeDefinition.setName(name); diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java index 6b911e036e..9bf149f840 100644 --- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java +++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java @@ -137,5 +137,6 @@ public enum ActionStatus { TOSCA_GET_FUNCTION_TYPE_DIVERGE, TOSCA_GET_FUNCTION_SCHEMA_DIVERGE, TOSCA_GET_FUNCTION_PROPERTY_DATA_TYPE_NOT_FOUND, - TOSCA_GET_FUNCTION_PROPERTY_NOT_FOUND + TOSCA_GET_FUNCTION_PROPERTY_NOT_FOUND, + TOSCA_GET_FUNCTION_INSTANCE_NOT_FOUND } diff --git a/catalog-ui/src/app/models/tosca-get-function.ts b/catalog-ui/src/app/models/tosca-get-function.ts new file mode 100644 index 0000000000..0fe0831215 --- /dev/null +++ b/catalog-ui/src/app/models/tosca-get-function.ts @@ -0,0 +1,33 @@ +/* + * - + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +import {PropertySource} from "./property-source"; +import {ToscaGetFunctionType} from "./tosca-get-function-type"; + +export class ToscaGetFunction { + propertyUniqueId: string; + propertyName: string; + propertySource: PropertySource; + sourceUniqueId: string; + sourceName: string; + functionType: ToscaGetFunctionType; + propertyPathFromSource: Array<string>; +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.ts b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.ts index 5ca119c075..822d8c9cdd 100644 --- a/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.ts +++ b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.ts @@ -39,7 +39,7 @@ import { DynamicElementComponent } from "../../ui/dynamic-element/dynamic-elemen export class InputsTableComponent { @Input() inputs: Array<InputFEModel>; - @Input() instanceNamesMap: Map<string, InstanceFeDetails>; + @Input() instanceNamesMap: { [key: string]: InstanceFeDetails }; @Input() readonly: boolean; @Input() isLoading: boolean; @Input() componentType: string; diff --git a/catalog-ui/src/app/ng2/components/logic/policies-table/policies-table.component.ts b/catalog-ui/src/app/ng2/components/logic/policies-table/policies-table.component.ts index 9613439859..9286dc6398 100644 --- a/catalog-ui/src/app/ng2/components/logic/policies-table/policies-table.component.ts +++ b/catalog-ui/src/app/ng2/components/logic/policies-table/policies-table.component.ts @@ -28,7 +28,7 @@ import { ModalService } from '../../../services/modal.service'; export class PoliciesTableComponent { @Input() policies: PolicyInstance[]; - @Input() instanceNamesMap: Map<string, InstanceFeDetails>; + @Input() instanceNamesMap: { [key: string]: InstanceFeDetails }; @Input() readonly: boolean; @Input() isLoading: boolean; @Output() deletePolicy: EventEmitter<any> = new EventEmitter<any>(); diff --git a/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.ts b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.ts index b79bec0942..f78728695c 100644 --- a/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.ts +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.ts @@ -33,7 +33,7 @@ import { ModalService } from '../../../services/modal.service'; export class PropertiesTableComponent implements OnChanges { @Input() fePropertiesMap: InstanceFePropertiesMap; - @Input() feInstanceNamesMap: Map<string, InstanceFeDetails>; + @Input() feInstanceNamesMap: { [key: string]: InstanceFeDetails }; @Input() selectedPropertyId: string; @Input() propertyNameSearchText: string; @Input() searchTerm: string; diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts index 2d491cd544..6584b4732b 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts @@ -61,15 +61,13 @@ import {UnsavedChangesComponent} from "app/ng2/components/ui/forms/unsaved-chang import {PropertyCreatorComponent} from "./property-creator/property-creator.component"; import {ModalService} from "../../services/modal.service"; import {DeclareListComponent} from "./declare-list/declare-list.component"; -import {PropertyDropdownValue, ToscaFunctionComponent} from "./tosca-function/tosca-function.component"; +import {ToscaFunctionComponent} from "./tosca-function/tosca-function.component"; import {CapabilitiesGroup, Capability} from "../../../models/capability"; import {ToscaPresentationData} from "../../../models/tosca-presentation"; import {Observable} from "rxjs"; -import {ToscaGetFunctionType} from "../../../models/tosca-get-function-type"; import {TranslateService} from "../../shared/translator/translate.service"; import {ToscaGetFunctionDtoBuilder} from '../../../models/tosca-get-function-dto'; -import {PropertySource} from '../../../models/property-source'; -import {ToscaGetFunctionTypeConverter} from '../../../models/tosca-get-function-type-converter'; +import {ToscaGetFunction} from "../../../models/tosca-get-function"; const SERVICE_SELF_TITLE = "SELF"; @Component({ @@ -80,7 +78,8 @@ export class PropertiesAssignmentComponent { title = "Properties & Inputs"; component: ComponentData; - componentInstanceNamesMap: Map<string, InstanceFeDetails> = new Map<string, InstanceFeDetails>();//instanceUniqueId, {name, iconClass} + componentInstanceNamesMap: { [key: string]: InstanceFeDetails } = {}; //key is the instance uniqueId + componentInstanceMap: Map<string, InstanceFeDetails> = new Map<string, InstanceFeDetails>(); //key is the instance uniqueId propertiesNavigationData = []; instancesNavigationData = []; @@ -183,6 +182,16 @@ export class PropertiesAssignmentComponent { this.instances.push(...response.groupInstances); this.instances.push(...response.policies); + if (response.componentInstances) { + response.componentInstances.forEach(instance => { + this.componentInstanceMap.set(instance.uniqueId, <InstanceFeDetails>{ + name: instance.name, + iconClass: instance.iconClass, + originArchived: instance.originArchived + }); + }); + } + _.forEach(response.policies, (policy: any) => { const newPolicy: InputFEModel = new InputFEModel(policy); this.inputsUtils.resetInputDefaultValue(newPolicy, policy.defaultValue); @@ -542,10 +551,8 @@ export class PropertiesAssignmentComponent { [ new ButtonModel(this.translateService.translate('MODAL_SAVE'), 'blue', () => { - const selectedToscaFunction = modal.instance.dynamicContent.instance.selectToscaFunction; - const selectedPropertyFromModal:PropertyDropdownValue = modal.instance.dynamicContent.instance.selectedProperty; - const toscaFunctionType: ToscaGetFunctionType = ToscaGetFunctionTypeConverter.convertFromString(selectedToscaFunction); - this.updateCheckedInstancePropertyGetFunctionValue(selectedPropertyFromModal, toscaFunctionType); + const toscaGetFunction: ToscaGetFunction = modal.instance.dynamicContent.instance.toscaGetFunction; + this.updateCheckedInstancePropertyGetFunctionValue(toscaGetFunction); modal.instance.close(); } ), @@ -558,6 +565,7 @@ export class PropertiesAssignmentComponent { const checkedInstanceProperty = this.buildCheckedInstanceProperty(); this.modalService.addDynamicContentToModalAndBindInputs(modal, ToscaFunctionComponent, { 'property': checkedInstanceProperty, + 'componentInstanceMap': this.componentInstanceMap }); modal.instance.open(); } @@ -570,20 +578,18 @@ export class PropertiesAssignmentComponent { this.updateInstanceProperty(checkedInstanceProperty); } - private updateCheckedInstancePropertyGetFunctionValue(propertyToGet: PropertyDropdownValue, toscaGetFunctionType: ToscaGetFunctionType) { + private updateCheckedInstancePropertyGetFunctionValue(toscaGetFunction: ToscaGetFunction) { const toscaGetFunctionBuilder: ToscaGetFunctionDtoBuilder = new ToscaGetFunctionDtoBuilder() - .withPropertyUniqueId(propertyToGet.propertyId) - .withFunctionType(toscaGetFunctionType) - .withPropertySource(PropertySource.SELF) - .withPropertyName(propertyToGet.propertyName) - .withSourceName(this.component.name) - .withSourceUniqueId(this.component.uniqueId); + .withPropertyUniqueId(toscaGetFunction.propertyUniqueId) + .withFunctionType(toscaGetFunction.functionType) + .withPropertySource(toscaGetFunction.propertySource) + .withPropertyName(toscaGetFunction.propertyName) + .withSourceName(toscaGetFunction.sourceName) + .withSourceUniqueId(toscaGetFunction.sourceUniqueId) + .withPropertyPathFromSource(toscaGetFunction.propertyPathFromSource); const checkedProperty: PropertyBEModel = this.buildCheckedInstanceProperty(); - if (propertyToGet.propertyPath && propertyToGet.propertyPath.length) { - toscaGetFunctionBuilder.withPropertyPathFromSource(propertyToGet.propertyPath); - } checkedProperty.toscaGetFunction = toscaGetFunctionBuilder.build(); this.updateInstanceProperty(checkedProperty); } diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/services/properties.utils.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/services/properties.utils.ts index 02dbf91868..70c9303c14 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/services/properties.utils.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/services/properties.utils.ts @@ -47,7 +47,9 @@ export class PropertiesUtils { if (this.dataTypeService.getDataTypeByModelAndTypeName(model, property.type)) { // if type not exist in data types remove property from list let newFEProp: PropertyFEModel = new PropertyFEModel(property); //Convert property to FE - + if (!newFEProp.parentUniqueId) { + newFEProp.parentUniqueId = instanceId; + } this.initValueObjectRef(newFEProp); //initialize valueObj AND creates flattened children propertyFeArray.push(newFEProp); newFEProp.updateExpandedChildPropertyId(newFEProp.name); //display only the first level of children diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.html b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.html index 851d7b6e77..1f81ebe425 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.html +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.html @@ -21,15 +21,22 @@ <loader [display]="isLoading" [loaderDelay]="500" [relative]="true" [size]="'large'"></loader> <form class="w-sdc-form"> <div class="i-sdc-form-item"> - <label class="i-sdc-form-label required">TOSCA function</label> - <select [(ngModel)]="selectToscaFunction" (change)="onToscaFunctionChange()" name="selectToscaFunction"> + <label class="i-sdc-form-label required">{{'TOSCA_FUNCTION_LABEL' | translate}}</label> + <select [(ngModel)]="toscaGetFunction.functionType" (change)="onToscaFunctionChange()" name="toscaFunctionType"> <option *ngFor="let toscaFunction of toscaFunctions" - [ngValue]="toscaFunction">{{toscaFunction}}</option> + [ngValue]="toscaFunction">{{toscaFunction | lowercase}}</option> + </select> + </div> + <div class="i-sdc-form-item" *ngIf="toscaGetFunction.functionType === TOSCA_FUNCTION_GET_PROPERTY"> + <label class="i-sdc-form-label required">{{'TOSCA_FUNCTION_PROPERTY_SOURCE_LABEL' | translate}}</label> + <select name="propertySource" [(ngModel)]="propertySource" (change)="onPropertySourceChange()"> + <option *ngFor="let propertySource of propertySourceList" + [ngValue]="propertySource">{{propertySource}}</option> </select> </div> <div *ngIf="showDropdown()" class="i-sdc-form-item"> <label class="i-sdc-form-label required">{{dropdownValuesLabel}}</label> - <select [(ngModel)]="selectedProperty" name="selectedProperty"> + <select [(ngModel)]="selectedProperty" name="selectedProperty" (change)="onPropertyChange()"> <option *ngFor="let value of propertyDropdownList" [ngValue]="value">{{value.propertyLabel}}</option> </select> </div> diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.ts index 6e013d7169..054a21f251 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.ts @@ -18,7 +18,7 @@ */ import {Component, Input} from '@angular/core'; -import {ComponentMetadata, DataTypeModel, PropertyBEModel} from 'app/models'; +import {ComponentMetadata, DataTypeModel, PropertyBEModel, PropertyModel} from 'app/models'; import {TopologyTemplateService} from "../../../services/component-services/topology-template.service"; import {WorkspaceService} from "../../workspace/workspace.service"; import {PropertiesService} from "../../../services/properties.service"; @@ -28,6 +28,9 @@ import {ToscaGetFunctionType} from "../../../../models/tosca-get-function-type"; import {TranslateService} from "../../../shared/translator/translate.service"; import {ComponentGenericResponse} from '../../../services/responses/component-generic-response'; import {Observable} from 'rxjs/Observable'; +import {PropertySource} from "../../../../models/property-source"; +import {InstanceFeDetails} from "../../../../models/instance-fe-details"; +import {ToscaGetFunction} from "../../../../models/tosca-get-function"; @Component({ selector: 'tosca-function', @@ -37,14 +40,20 @@ import {Observable} from 'rxjs/Observable'; export class ToscaFunctionComponent { @Input() property: PropertyBEModel; + @Input() componentInstanceMap: Map<string, InstanceFeDetails> = new Map<string, InstanceFeDetails>(); + + TOSCA_FUNCTION_GET_PROPERTY = ToscaGetFunctionType.GET_PROPERTY; - selectToscaFunction; selectedProperty: PropertyDropdownValue; isLoading: boolean = false; propertyDropdownList: Array<PropertyDropdownValue> = []; toscaFunctions: Array<string> = []; + propertySourceList: Array<string> = []; + instanceNameAndIdMap: Map<string, string> = new Map<string, string>(); dropdownValuesLabel: string; dropDownErrorMsg: string; + propertySource: string + toscaGetFunction: ToscaGetFunction = new ToscaGetFunction(); private componentMetadata: ComponentMetadata; @@ -58,20 +67,55 @@ export class ToscaFunctionComponent { ngOnInit() { this.componentMetadata = this.workspaceService.metadata; this.loadToscaFunctions(); + this.loadPropertySourceDropdown(); } private loadToscaFunctions(): void { - this.toscaFunctions.push(ToscaGetFunctionType.GET_INPUT.toLowerCase()); - this.toscaFunctions.push(ToscaGetFunctionType.GET_PROPERTY.toLowerCase()); + this.toscaFunctions.push(ToscaGetFunctionType.GET_INPUT); + this.toscaFunctions.push(ToscaGetFunctionType.GET_PROPERTY); + } + + private loadPropertySourceDropdown() { + this.propertySourceList.push(PropertySource.SELF); + this.componentInstanceMap.forEach((value, key) => { + const instanceName = value.name; + this.instanceNameAndIdMap.set(instanceName, key); + if (instanceName !== PropertySource.SELF) { + this.addToPropertySource(instanceName); + } + }); + } + + private addToPropertySource(source: string) { + this.propertySourceList.push(source); + this.propertySourceList.sort((a, b) => { + if (a === PropertySource.SELF) { + return -1; + } else if (b === PropertySource.SELF) { + return 1; + } + + return a.localeCompare(b); + }); } onToscaFunctionChange(): void { - this.loadDropdownValueLabel(); - this.loadDropdownValues(); + this.toscaGetFunction.propertyUniqueId = undefined; + this.toscaGetFunction.propertyName = undefined; + this.toscaGetFunction.propertySource = undefined; + this.toscaGetFunction.sourceUniqueId = undefined; + this.toscaGetFunction.sourceName = undefined; + this.toscaGetFunction.propertyPathFromSource = undefined; + this.propertySource = undefined; + if (this.isGetInputSelected()) { + this.setSelfPropertySource(); + this.loadDropdownValueLabel(); + this.loadDropdownValues(); + } } private loadDropdownValueLabel(): void { - if (!this.selectToscaFunction) { + if (!this.toscaGetFunction.functionType) { return; } if (this.isGetInputSelected()) { @@ -82,7 +126,7 @@ export class ToscaFunctionComponent { } private loadDropdownValues(): void { - if (!this.selectToscaFunction) { + if (!this.toscaGetFunction.functionType) { return; } this.resetDropDown(); @@ -96,30 +140,59 @@ export class ToscaFunctionComponent { private loadPropertiesInDropdown() { this.startLoading(); - let propertiesObservable: Observable<ComponentGenericResponse> + const propertiesObservable: Observable<ComponentGenericResponse> = this.getPropertyObservable(); + propertiesObservable.subscribe( (response: ComponentGenericResponse) => { + const properties: PropertyBEModel[] = this.extractProperties(response); + if (!properties || properties.length === 0) { + const msgCode = this.isGetInputSelected() ? 'TOSCA_FUNCTION_NO_INPUT_FOUND' : 'TOSCA_FUNCTION_NO_PROPERTY_FOUND'; + this.dropDownErrorMsg = this.translateService.translate(msgCode, {type: this.property.type}); + return; + } + this.addPropertiesToDropdown(properties); + if (this.propertyDropdownList.length == 0) { + const msgCode = this.isGetInputSelected() ? 'TOSCA_FUNCTION_NO_INPUT_FOUND' : 'TOSCA_FUNCTION_NO_PROPERTY_FOUND'; + this.dropDownErrorMsg = this.translateService.translate(msgCode, {type: this.property.type}); + } + }, (error) => { + console.error('An error occurred while loading properties.', error); + }, () => { + this.stopLoading(); + }); + } + + private extractProperties(componentGenericResponse: ComponentGenericResponse): PropertyBEModel[] { if (this.isGetInputSelected()) { - propertiesObservable = this.topologyTemplateService.getComponentInputsValues(this.componentMetadata.componentType, this.componentMetadata.uniqueId); - } else if (this.isGetPropertySelected()) { - propertiesObservable = this.topologyTemplateService.findAllComponentProperties(this.componentMetadata.componentType, this.componentMetadata.uniqueId); + return componentGenericResponse.inputs; + } + if (this.isGetPropertySelected()) { + if (this.propertySource === PropertySource.SELF) { + return componentGenericResponse.properties; + } + const componentInstanceProperties: PropertyModel[] = componentGenericResponse.componentInstancesProperties[this.instanceNameAndIdMap.get(this.propertySource)]; + return this.removeSelectedProperty(componentInstanceProperties); + } + } + + private getPropertyObservable(): Observable<ComponentGenericResponse> { + if (this.isGetInputSelected()) { + return this.topologyTemplateService.getComponentInputsValues(this.componentMetadata.componentType, this.componentMetadata.uniqueId); + } + if (this.isGetPropertySelected()) { + if (this.propertySource === PropertySource.SELF) { + return this.topologyTemplateService.findAllComponentProperties(this.componentMetadata.componentType, this.componentMetadata.uniqueId); + } + return this.topologyTemplateService.getComponentInstanceProperties(this.componentMetadata.componentType, this.componentMetadata.uniqueId); } - propertiesObservable - .subscribe( (response: ComponentGenericResponse) => { - let properties: PropertyBEModel[] = this.isGetInputSelected() ? response.inputs : response.properties; - if (!properties || properties.length === 0) { - const msgCode = this.isGetInputSelected() ? 'TOSCA_FUNCTION_NO_INPUT_FOUND' : 'TOSCA_FUNCTION_NO_PROPERTY_FOUND'; - this.dropDownErrorMsg = this.translateService.translate(msgCode, {type: this.property.type}); - return; - } - this.addPropertiesToDropdown(properties); - if (this.propertyDropdownList.length == 0) { - const msgCode = this.isGetInputSelected() ? 'TOSCA_FUNCTION_NO_INPUT_FOUND' : 'TOSCA_FUNCTION_NO_PROPERTY_FOUND'; - this.dropDownErrorMsg = this.translateService.translate(msgCode, {type: this.property.type}); - } - }, (error) => { - console.error('An error occurred while loading properties.', error); - }, () => { - this.stopLoading(); - }); + } + + private removeSelectedProperty(componentInstanceProperties: PropertyModel[]): PropertyModel[] { + if (!componentInstanceProperties) { + return []; + } + return componentInstanceProperties.filter(property => + (property.uniqueId !== this.property.uniqueId) || + (property.uniqueId === this.property.uniqueId && property.resourceInstanceUniqueId !== this.property.parentUniqueId) + ); } private addPropertyToDropdown(propertyDropdownValue: PropertyDropdownValue) { @@ -134,7 +207,6 @@ export class ToscaFunctionComponent { propertyName: property.name, propertyId: property.uniqueId, propertyLabel: property.name, - toscaFunction: this.selectToscaFunction, propertyPath: [property.name] }); } else if (this.isComplexType(property.type)) { @@ -155,7 +227,6 @@ export class ToscaFunctionComponent { propertyName: dataTypeProperty.name, propertyId: parentPropertyList[0].uniqueId, propertyLabel: parentPropertyList.map(property => property.name).join('->') + '->' + dataTypeProperty.name, - toscaFunction: this.selectToscaFunction, propertyPath: [...parentPropertyList.map(property => property.name), dataTypeProperty.name] }); } else if (PROPERTY_DATA.SIMPLE_TYPES.indexOf(dataTypeProperty.type) === -1) { @@ -165,11 +236,11 @@ export class ToscaFunctionComponent { } private isGetPropertySelected() { - return this.selectToscaFunction === ToscaGetFunctionType.GET_PROPERTY.toLowerCase(); + return this.toscaGetFunction.functionType === ToscaGetFunctionType.GET_PROPERTY; } private isGetInputSelected() { - return this.selectToscaFunction === ToscaGetFunctionType.GET_INPUT.toLowerCase(); + return this.toscaGetFunction.functionType === ToscaGetFunctionType.GET_INPUT; } private isComplexType(propertyType: string) { @@ -185,7 +256,42 @@ export class ToscaFunctionComponent { } showDropdown(): boolean { - return this.selectToscaFunction && !this.isLoading && !this.dropDownErrorMsg; + if (this.toscaGetFunction.functionType === ToscaGetFunctionType.GET_PROPERTY) { + return this.toscaGetFunction.propertySource && !this.isLoading && !this.dropDownErrorMsg; + } + + return this.toscaGetFunction.functionType && !this.isLoading && !this.dropDownErrorMsg; + } + + onPropertySourceChange() { + if (!this.toscaGetFunction.functionType || !this.propertySource) { + return; + } + this.toscaGetFunction.propertyUniqueId = undefined; + this.toscaGetFunction.propertyName = undefined; + this.toscaGetFunction.propertyPathFromSource = undefined; + if (this.propertySource === PropertySource.SELF) { + this.setSelfPropertySource(); + } else { + this.toscaGetFunction.propertySource = PropertySource.INSTANCE; + this.toscaGetFunction.sourceName = this.propertySource; + this.toscaGetFunction.sourceUniqueId = this.instanceNameAndIdMap.get(this.propertySource); + } + this.loadDropdownValueLabel(); + this.resetDropDown(); + this.loadPropertiesInDropdown(); + } + + private setSelfPropertySource() { + this.toscaGetFunction.propertySource = PropertySource.SELF; + this.toscaGetFunction.sourceName = this.componentMetadata.name; + this.toscaGetFunction.sourceUniqueId = this.componentMetadata.uniqueId; + } + + onPropertyChange() { + this.toscaGetFunction.propertyUniqueId = this.selectedProperty.propertyId; + this.toscaGetFunction.propertyName = this.selectedProperty.propertyName; + this.toscaGetFunction.propertyPathFromSource = this.selectedProperty.propertyPath; } } @@ -194,6 +300,5 @@ export interface PropertyDropdownValue { propertyName: string; propertyId: string; propertyLabel: string; - toscaFunction: ToscaGetFunctionType; propertyPath: Array<string>; } diff --git a/catalog-ui/src/assets/languages/en_US.json b/catalog-ui/src/assets/languages/en_US.json index 0aef293c9c..d869a43a64 100644 --- a/catalog-ui/src/assets/languages/en_US.json +++ b/catalog-ui/src/assets/languages/en_US.json @@ -512,6 +512,7 @@ "DELETE_POLICY_MSG": "Are you sure you want to delete policy '{{policyName}}'?", "=========== PROPERTIES ASSIGNMENT TOSCA FUNCTION BUTTON ===========": "", "TOSCA_FUNCTION_LABEL": "TOSCA function", + "TOSCA_FUNCTION_PROPERTY_SOURCE_LABEL": "Property Source", "CLEAR_VALUE_LABEL": "Clear Value", "INPUT_DROPDOWN_LABEL": "Input", "TOSCA_FUNCTION_PROPERTY_DROPDOWN_LABEL": "Property", |