Support TOSCA get_attribute function 30/129630/5
authorandre.schmid <andre.schmid@est.tech>
Wed, 15 Jun 2022 14:30:40 +0000 (15:30 +0100)
committerMichael Morris <michael.morris@est.tech>
Wed, 22 Jun 2022 20:36:22 +0000 (20:36 +0000)
Adds support to TOSCA get_attribute function in the Property Assignment
TOSCA Function modal.

Change-Id: I73dda215a7c9d7fecf0803cc259634279c3bdfb6
Issue-ID: SDC-4053
Signed-off-by: andre.schmid <andre.schmid@est.tech>
12 files changed:
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogicTest.java
catalog-be/src/test/resources/config/catalog-be/error-configuration.yaml
catalog-model/src/main/java/org/openecomp/sdc/be/model/AttributeDefinition.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/PropertyDefinition.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/ToscaPropertyData.java [new file with mode: 0644]
catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.html
catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.ts
catalog-ui/src/app/ng2/services/component-services/topology-template.service.ts
catalog-ui/src/assets/languages/en_US.json
common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/ToscaGetFunctionDataDefinition.java
common-be/src/test/java/org/openecomp/sdc/be/datatypes/elements/ToscaGetFunctionDataDefinitionTest.java

index ab01b99..4bf8172 100644 (file)
@@ -107,6 +107,7 @@ import org.openecomp.sdc.be.model.RequirementCapabilityRelDef;
 import org.openecomp.sdc.be.model.RequirementDefinition;
 import org.openecomp.sdc.be.model.Resource;
 import org.openecomp.sdc.be.model.Service;
+import org.openecomp.sdc.be.model.ToscaPropertyData;
 import org.openecomp.sdc.be.model.User;
 import org.openecomp.sdc.be.model.jsonjanusgraph.config.ContainerInstanceTypesData;
 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations;
@@ -2387,13 +2388,25 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
 
             return;
         }
+        if (toscaGetFunction.getFunctionType() == ToscaGetFunctionType.GET_ATTRIBUTE) {
+            if (toscaGetFunction.getPropertySource() == PropertySource.SELF) {
+                validateGetFunction(property, parentComponent.getAttributes(), parentComponent.getModel());
+            } else if (toscaGetFunction.getPropertySource() == PropertySource.INSTANCE) {
+                final ComponentInstance componentInstance =
+                    parentComponent.getComponentInstanceById(toscaGetFunction.getSourceUniqueId())
+                        .orElseThrow(ToscaGetFunctionExceptionSupplier.instanceNotFound(toscaGetFunction.getSourceName()));
+                validateGetFunction(property, componentInstance.getAttributes(), parentComponent.getModel());
+            }
+
+            return;
+        }
 
         throw ToscaGetFunctionExceptionSupplier.functionNotSupported(toscaGetFunction.getFunctionType()).get();
     }
 
-    private <T extends PropertyDefinition, U extends PropertyDefinition> void validateGetFunction(final T property,
-                                                                                                  final List<U> parentProperties,
-                                                                                                  final String model) {
+    private <T extends PropertyDefinition> void validateGetFunction(final T property,
+                                                                    final List<? extends ToscaPropertyData> parentProperties,
+                                                                    final String model) {
         final ToscaGetFunctionDataDefinition toscaGetFunction = property.getToscaGetFunction();
         if (CollectionUtils.isEmpty(parentProperties)) {
             throw ToscaGetFunctionExceptionSupplier
@@ -2402,7 +2415,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
                 ).get();
         }
         final String getFunctionPropertyUniqueId = toscaGetFunction.getPropertyUniqueId();
-        T referredProperty = (T) parentProperties.stream()
+        ToscaPropertyData referredProperty = parentProperties.stream()
             .filter(property1 -> getFunctionPropertyUniqueId.equals(property1.getUniqueId()))
             .findFirst()
             .orElseThrow(ToscaGetFunctionExceptionSupplier
@@ -2423,8 +2436,9 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         }
     }
 
-    private <T extends PropertyDefinition> T findSubProperty(final T referredProperty, final ToscaGetFunctionDataDefinition toscaGetFunction,
-                                                             final String model) {
+    private ToscaPropertyData findSubProperty(final ToscaPropertyData referredProperty,
+                                              final ToscaGetFunctionDataDefinition toscaGetFunction,
+                                              final String model) {
         final Map<String, DataTypeDefinition> dataTypeMap = loadDataTypes(model);
         final List<String> propertyPathFromSource = toscaGetFunction.getPropertyPathFromSource();
         DataTypeDefinition dataType = dataTypeMap.get(referredProperty.getType());
@@ -2432,10 +2446,10 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
             throw ToscaGetFunctionExceptionSupplier
                 .propertyDataTypeNotFound(propertyPathFromSource.get(0), referredProperty.getType(), toscaGetFunction.getFunctionType()).get();
         }
-        T foundProperty = referredProperty;
+        ToscaPropertyData foundProperty = referredProperty;
         for (int i = 1; i < propertyPathFromSource.size(); i++) {
             final String currentPropertyName = propertyPathFromSource.get(i);
-            foundProperty = (T) dataType.getProperties().stream()
+            foundProperty = dataType.getProperties().stream()
                 .filter(propertyDefinition -> currentPropertyName.equals(propertyDefinition.getName())).findFirst()
                 .orElseThrow(
                     ToscaGetFunctionExceptionSupplier
index bf3ec3c..cd916d0 100644 (file)
@@ -678,54 +678,6 @@ class ComponentInstanceBusinessLogicTest {
         assertEquals(expectedResponse.getStatus(), actualResponse.getStatus());
     }
 
-    @Test
-    void testToscaGetFunctionValidation_toscaFunctionNotSupportedTest() {
-        final String userId = "userId";
-        final String containerComponentId = "containerComponentId";
-        final String containerComponentName = "containerComponentName";
-        final String resourceInstanceId = "resourceInstanceId";
-        final List<ComponentInstanceProperty> properties = new ArrayList<>();
-        final ComponentInstanceProperty propertyGetInput = new ComponentInstanceProperty();
-        propertyGetInput.setName("anyName");
-        final var toscaGetFunction = new ToscaGetFunctionDataDefinition();
-        toscaGetFunction.setFunctionType(ToscaGetFunctionType.GET_ATTRIBUTE);
-        toscaGetFunction.setPropertySource(PropertySource.SELF);
-        toscaGetFunction.setPropertyPathFromSource(List.of("sourcePath"));
-        toscaGetFunction.setSourceName("sourceName");
-        toscaGetFunction.setSourceUniqueId("sourceUniqueId");
-        toscaGetFunction.setPropertyName("propertyName");
-        toscaGetFunction.setPropertyUniqueId("propertyId");
-        propertyGetInput.setToscaGetFunction(toscaGetFunction);
-        properties.add(propertyGetInput);
-
-        final Component component = new Service();
-        component.setName(containerComponentName);
-        component.setUniqueId(containerComponentId);
-        component.setLastUpdaterUserId(userId);
-        component.setLifecycleState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
-
-        final Map<String, List<ComponentInstanceProperty>> componentInstanceProps = new HashMap<>();
-        componentInstanceProps.put(resourceInstanceId, properties);
-        component.setComponentInstancesProperties(componentInstanceProps);
-
-        final ComponentInstance resourceInstance = createComponentInstance("componentInstance1");
-        resourceInstance.setUniqueId(resourceInstanceId);
-        component.setComponentInstances(List.of(resourceInstance));
-
-        mockComponentForToscaGetFunctionValidation(component);
-        //when
-        final Either<List<ComponentInstanceProperty>, ResponseFormat> responseFormatEither =
-            componentInstanceBusinessLogic
-                .createOrUpdatePropertiesValues(ComponentTypeEnum.RESOURCE_INSTANCE, containerComponentId, resourceInstanceId, properties, userId);
-        //then
-        assertTrue(responseFormatEither.isRight(), "Expecting an error");
-        final ResponseFormat actualResponse = responseFormatEither.right().value();
-        final ResponseFormat expectedResponse = ToscaGetFunctionExceptionSupplier
-            .functionNotSupported(toscaGetFunction.getFunctionType()).get().getResponseFormat();
-        assertEquals(expectedResponse.getFormattedMessage(), actualResponse.getFormattedMessage());
-        assertEquals(expectedResponse.getStatus(), actualResponse.getStatus());
-    }
-
     @ParameterizedTest
     @MethodSource("getToscaFunctionForValidation")
     void testToscaGetFunctionValidation_AttributesNotFoundTest(final ToscaGetFunctionDataDefinition toscaGetFunction,
@@ -762,9 +714,8 @@ class ComponentInstanceBusinessLogicTest {
         //then
         assertTrue(responseFormatEither.isRight(), "Expecting an error");
         final ResponseFormat actualResponse = responseFormatEither.right().value();
-        final ResponseFormat expectedResponse = expectedValidationResponse;
-        assertEquals(expectedResponse.getFormattedMessage(), actualResponse.getFormattedMessage());
-        assertEquals(expectedResponse.getStatus(), actualResponse.getStatus());
+        assertEquals(expectedValidationResponse.getFormattedMessage(), actualResponse.getFormattedMessage());
+        assertEquals(expectedValidationResponse.getStatus(), actualResponse.getStatus());
     }
 
     @Test
index 2100dc8..293bd49 100644 (file)
@@ -2392,3 +2392,12 @@ errors:
         message: "The %1 '%2' type '%3' was not found.",
         messageId: "SVC4170"
     }
+
+    #-----------SVC4172---------------------------
+    #%1 - TOSCA function attribute
+    TOSCA_FUNCTION_MISSING_ATTRIBUTE: {
+        code: 400,
+        message: "Missing TOSCA function '%1'.",
+        messageId: "SVC4172"
+    }
+
index d1bcedc..be9bee0 100644 (file)
@@ -21,9 +21,10 @@ package org.openecomp.sdc.be.model;
 
 import lombok.NoArgsConstructor;
 import org.openecomp.sdc.be.datatypes.elements.AttributeDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
 
 @NoArgsConstructor
-public class AttributeDefinition extends AttributeDataDefinition implements IOperationParameter, IComplexDefaultValue {
+public class AttributeDefinition extends AttributeDataDefinition implements IOperationParameter, IComplexDefaultValue, ToscaPropertyData {
 
     public AttributeDefinition(final AttributeDataDefinition attributeDataDefinition) {
         super(attributeDataDefinition);
@@ -49,4 +50,14 @@ public class AttributeDefinition extends AttributeDataDefinition implements IOpe
         return "AttributeDefinition{" + "name=" + getName() + "uniqueId=" + getUniqueId() + "ownerId=" + getOwnerId() + "type=" + getType()
             + "description=" + getDescription() + "default=" + getDefaultValue() + '}';
     }
+
+    @Override
+    public String getSchemaType() {
+        final SchemaDefinition schema = getSchema();
+        if (schema == null || schema.getProperty() == null) {
+            return null;
+        }
+        return schema.getProperty().getType();
+    }
+
 }
index 6e313ed..d9add3f 100644 (file)
@@ -31,7 +31,7 @@ import org.apache.commons.collections.CollectionUtils;
 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
 import org.openecomp.sdc.be.model.operations.impl.PropertyOperation;
 
-public class PropertyDefinition extends PropertyDataDefinition implements IOperationParameter, IComplexDefaultValue {
+public class PropertyDefinition extends PropertyDataDefinition implements IOperationParameter, IComplexDefaultValue, ToscaPropertyData {
 
     private List<PropertyConstraint> constraints;
 
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/ToscaPropertyData.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ToscaPropertyData.java
new file mode 100644 (file)
index 0000000..14c9575
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * -
+ *  ============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=========================================================
+ */
+
+package org.openecomp.sdc.be.model;
+
+/**
+ * Represents basic/common TOSCA Property, Attribute or Input methods
+ */
+public interface ToscaPropertyData {
+    String getUniqueId();
+    String getType();
+    String getSchemaType();
+}
index f0db645..b6b313d 100644 (file)
                 [ngValue]="toscaFunction">{{toscaFunction | lowercase}}</option>
       </select>
     </div>
-    <div class="i-sdc-form-item" *ngIf="toscaGetFunction.functionType === TOSCA_FUNCTION_GET_PROPERTY">
+    <div class="i-sdc-form-item" *ngIf="showPropertySourceDropdown()">
       <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">
+    <div *ngIf="showPropertyDropdown()" class="i-sdc-form-item">
       <label class="i-sdc-form-label required">{{dropdownValuesLabel}}</label>
       <select [(ngModel)]="selectedProperty" name="selectedProperty" (change)="onPropertyChange()">
         <option *ngFor="let value of propertyDropdownList" [ngValue]="value">{{value.propertyLabel}}</option>
index 4eefbcb..b71a61d 100644 (file)
@@ -18,7 +18,7 @@
  */
 
 import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
-import {ComponentMetadata, DataTypeModel, PropertyBEModel, PropertyModel} from 'app/models';
+import {AttributeModel, 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";
@@ -82,8 +82,6 @@ export class ToscaFunctionComponent implements OnInit {
         'toscaGetFunction': this.toscaGetFunctionForm
     });
 
-    TOSCA_FUNCTION_GET_PROPERTY = ToscaGetFunctionType.GET_PROPERTY;
-
     selectedProperty: PropertyDropdownValue;
     isLoading: boolean = false;
     propertyDropdownList: Array<PropertyDropdownValue> = [];
@@ -123,7 +121,7 @@ export class ToscaFunctionComponent implements OnInit {
         }
         this.toscaGetFunction = new ToscaGetFunction(this.property.toscaGetFunction);
         this.toscaGetFunctionForm.setValue(this.toscaGetFunction);
-        if (this.toscaGetFunction.functionType === ToscaGetFunctionType.GET_PROPERTY) {
+        if (this.isGetPropertySelected() || this.isGetAttributeSelected()) {
             if (this.toscaGetFunction.propertySource === PropertySource.SELF) {
                 this.propertySource = PropertySource.SELF;
             } else {
@@ -138,6 +136,7 @@ export class ToscaFunctionComponent implements OnInit {
     }
 
     private loadToscaFunctions(): void {
+        this.toscaFunctions.push(ToscaGetFunctionType.GET_ATTRIBUTE);
         this.toscaFunctions.push(ToscaGetFunctionType.GET_INPUT);
         this.toscaFunctions.push(ToscaGetFunctionType.GET_PROPERTY);
     }
@@ -210,6 +209,8 @@ export class ToscaFunctionComponent implements OnInit {
             this.dropdownValuesLabel = this.translateService.translate('INPUT_DROPDOWN_LABEL');
         } else if (this.isGetPropertySelected()) {
             this.dropdownValuesLabel = this.translateService.translate('TOSCA_FUNCTION_PROPERTY_DROPDOWN_LABEL');
+        } else if (this.isGetAttributeSelected()) {
+            this.dropdownValuesLabel = this.translateService.translate('TOSCA_FUNCTION_ATTRIBUTE_DROPDOWN_LABEL');
         }
     }
 
@@ -231,19 +232,20 @@ export class ToscaFunctionComponent implements OnInit {
         this.startLoading();
         const propertiesObservable: Observable<ComponentGenericResponse> = this.getPropertyObservable();
         propertiesObservable.subscribe( (response: ComponentGenericResponse) => {
-            const properties: PropertyBEModel[] = this.extractProperties(response);
+            const properties: Array<PropertyBEModel | AttributeModel> = this.extractProperties(response);
             if (!properties || properties.length === 0) {
-                const msgCode = this.isGetInputSelected() ? 'TOSCA_FUNCTION_NO_INPUT_FOUND' : 'TOSCA_FUNCTION_NO_PROPERTY_FOUND';
+                const msgCode = this.getNotFoundMsgCode();
                 this.dropDownErrorMsg = this.translateService.translate(msgCode, {type: this.propertyTypeToString()});
                 return;
             }
             this.addPropertiesToDropdown(properties);
             if (this.propertyDropdownList.length == 0) {
-                const msgCode = this.isGetInputSelected() ? 'TOSCA_FUNCTION_NO_INPUT_FOUND' : 'TOSCA_FUNCTION_NO_PROPERTY_FOUND';
+                const msgCode = this.getNotFoundMsgCode();
                 this.dropDownErrorMsg = this.translateService.translate(msgCode, {type: this.propertyTypeToString()});
             }
         }, (error) => {
             console.error('An error occurred while loading properties.', error);
+            this.stopLoading();
         }, () => {
             if (onComplete) {
                 onComplete();
@@ -252,6 +254,20 @@ export class ToscaFunctionComponent implements OnInit {
         });
     }
 
+    private getNotFoundMsgCode(): string {
+        if (this.isGetInputSelected()) {
+            return 'TOSCA_FUNCTION_NO_INPUT_FOUND';
+        }
+        if (this.isGetAttributeSelected()) {
+            return 'TOSCA_FUNCTION_NO_ATTRIBUTE_FOUND';
+        }
+        if (this.isGetPropertySelected()) {
+            return 'TOSCA_FUNCTION_NO_PROPERTY_FOUND';
+        }
+
+        return undefined;
+    }
+
     private propertyTypeToString() {
         if (this.property.schemaType) {
             return `${this.property.type} of ${this.property.schemaType}`;
@@ -259,7 +275,7 @@ export class ToscaFunctionComponent implements OnInit {
         return this.property.type;
     }
 
-    private extractProperties(componentGenericResponse: ComponentGenericResponse): PropertyBEModel[] {
+    private extractProperties(componentGenericResponse: ComponentGenericResponse): Array<PropertyBEModel | AttributeModel> {
         if (this.isGetInputSelected()) {
             return componentGenericResponse.inputs;
         }
@@ -270,6 +286,10 @@ export class ToscaFunctionComponent implements OnInit {
             const componentInstanceProperties: PropertyModel[] = componentGenericResponse.componentInstancesProperties[this.instanceNameAndIdMap.get(this.propertySource)];
             return this.removeSelectedProperty(componentInstanceProperties);
         }
+        if (this.propertySource === PropertySource.SELF) {
+            return componentGenericResponse.attributes;
+        }
+        return componentGenericResponse.componentInstancesAttributes[this.instanceNameAndIdMap.get(this.propertySource)];
     }
 
     private getPropertyObservable(): Observable<ComponentGenericResponse> {
@@ -282,6 +302,12 @@ export class ToscaFunctionComponent implements OnInit {
             }
             return this.topologyTemplateService.getComponentInstanceProperties(this.componentMetadata.componentType, this.componentMetadata.uniqueId);
         }
+        if (this.isGetAttributeSelected()) {
+            if (this.propertySource === PropertySource.SELF) {
+                return this.topologyTemplateService.findAllComponentAttributes(this.componentMetadata.componentType, this.componentMetadata.uniqueId);
+            }
+            return this.topologyTemplateService.findAllComponentInstanceAttributes(this.componentMetadata.componentType, this.componentMetadata.uniqueId);
+        }
     }
 
     private removeSelectedProperty(componentInstanceProperties: PropertyModel[]): PropertyModel[] {
@@ -299,7 +325,7 @@ export class ToscaFunctionComponent implements OnInit {
         this.propertyDropdownList.sort((a, b) => a.propertyLabel.localeCompare(b.propertyLabel));
     }
 
-    private addPropertiesToDropdown(properties: PropertyBEModel[]): void {
+    private addPropertiesToDropdown(properties: Array<PropertyBEModel | AttributeModel>): void {
         for (const property of properties) {
             if (this.hasSameType(property)) {
                 this.addPropertyToDropdown({
@@ -314,7 +340,8 @@ export class ToscaFunctionComponent implements OnInit {
         }
     }
 
-    private fillPropertyDropdownWithMatchingChildProperties(inputProperty: PropertyBEModel, parentPropertyList: Array<PropertyBEModel> = []): void {
+    private fillPropertyDropdownWithMatchingChildProperties(inputProperty: PropertyBEModel | AttributeModel,
+                                                            parentPropertyList: Array<PropertyBEModel | AttributeModel> = []): void {
         const dataTypeFound: DataTypeModel = this.dataTypeService.getDataTypeByModelAndTypeName(this.componentMetadata.model, inputProperty.type);
         if (!dataTypeFound || !dataTypeFound.properties) {
             return;
@@ -334,7 +361,7 @@ export class ToscaFunctionComponent implements OnInit {
         });
     }
 
-    private hasSameType(property: PropertyBEModel) {
+    private hasSameType(property: PropertyBEModel | AttributeModel) {
         if (this.typeHasSchema(this.property.type)) {
             if (!property.schema || !property.schema.property) {
                 return false;
@@ -349,6 +376,10 @@ export class ToscaFunctionComponent implements OnInit {
         return this.toscaGetFunction.functionType === ToscaGetFunctionType.GET_PROPERTY;
     }
 
+    private isGetAttributeSelected(): boolean {
+        return this.toscaGetFunction.functionType === ToscaGetFunctionType.GET_ATTRIBUTE;
+    }
+
     private isGetInputSelected(): boolean {
         return this.toscaGetFunction.functionType === ToscaGetFunctionType.GET_INPUT;
     }
@@ -369,8 +400,8 @@ export class ToscaFunctionComponent implements OnInit {
         this.isLoading = true;
     }
 
-    showDropdown(): boolean {
-        if (this.toscaGetFunction.functionType === ToscaGetFunctionType.GET_PROPERTY) {
+    showPropertyDropdown(): boolean {
+        if (this.isGetPropertySelected() || this.isGetAttributeSelected()) {
             return this.toscaGetFunction.propertySource && !this.isLoading && !this.dropDownErrorMsg;
         }
 
@@ -416,6 +447,10 @@ export class ToscaFunctionComponent implements OnInit {
     showClearButton(): boolean {
         return this.allowClear && this.toscaGetFunction.functionType !== undefined;
     }
+
+    showPropertySourceDropdown(): boolean {
+        return this.isGetPropertySelected() || this.isGetAttributeSelected();
+    }
 }
 
 export interface PropertyDropdownValue {
index 92a12c8..a2abb38 100644 (file)
  */
 
 import * as _ from "lodash";
-import {Injectable, Inject} from '@angular/core';
+import {Inject, Injectable} from '@angular/core';
 import {Observable} from 'rxjs/Observable';
 import 'rxjs/add/operator/map';
 import 'rxjs/add/operator/toPromise';
 import {
+    ArtifactModel,
+    AttributeModel,
+    Capability,
     Component,
+    FilterPropertiesAssignmentData,
+    IFileDownload,
     InputBEModel,
     InstancePropertiesAPIMap,
-    FilterPropertiesAssignmentData,
-    ArtifactModel,
+    OperationModel,
     PropertyModel,
-    IFileDownload,
-    AttributeModel,
-    Capability, Requirement, BEOperationModel, InterfaceModel
+    Requirement
 } from "app/models";
-import {ArtifactGroupType, COMPONENT_FIELDS} from "app/utils";
+import {API_QUERY_PARAMS, ArtifactGroupType, COMPONENT_FIELDS} from "app/utils";
 import {ComponentGenericResponse} from "../responses/component-generic-response";
 import {InstanceBePropertiesMap} from "../../../models/properties-inputs/property-fe-map";
-import {API_QUERY_PARAMS} from "app/utils";
 import {ComponentType, ServerTypeUrl, SERVICE_FIELDS} from "../../../utils/constants";
-import {SdcConfigToken, ISdcConfig} from "../../config/sdc-config.config";
+import {ISdcConfig, SdcConfigToken} from "../../config/sdc-config.config";
 import {IDependenciesServerResponse} from "../responses/dependencies-server-response";
 import {AutomatedUpgradeGenericResponse} from "../responses/automated-upgrade-response";
 import {IAutomatedUpgradeRequestObj} from "../../pages/automated-upgrade/automated-upgrade.service";
@@ -50,26 +51,15 @@ import {ComponentInstance} from "../../../models/componentsInstances/componentIn
 import {CommonUtils} from "../../../utils/common-utils";
 import {RelationshipModel} from "../../../models/graph/relationship";
 import {ServiceGenericResponse} from "../responses/service-generic-response";
-import { HttpClient, HttpParams, HttpHeaders } from "@angular/common/http";
-import { HttpHelperService } from "../http-hepler.service";
-import {
-    Component as TopologyTemplate,
-    FullComponentInstance,
-    Service,
-    OperationModel,
-} from 'app/models';
-import { ConsumptionInput } from "../../components/logic/service-consumption/service-consumption.component";
-import { ConstraintObject } from "../../components/logic/service-dependencies/service-dependencies.component";
-import { ComponentMetadata } from "../../../models/component-metadata";
-import { PolicyInstance } from "../../../models/graph/zones/policy-instance";
-import { PropertyBEModel } from "../../../models/properties-inputs/property-be-model";
+import {HttpClient, HttpHeaders, HttpParams} from "@angular/common/http";
+import {HttpHelperService} from "../http-hepler.service";
+import {ConsumptionInput} from "../../components/logic/service-consumption/service-consumption.component";
+import {ConstraintObject} from "../../components/logic/service-dependencies/service-dependencies.component";
+import {PolicyInstance} from "../../../models/graph/zones/policy-instance";
+import {PropertyBEModel} from "../../../models/properties-inputs/property-be-model";
 import {map} from "rxjs/operators";
 import {CapabilitiesConstraintObject} from "../../components/logic/capabilities-constraint/capabilities-constraint.component";
-import {
-    BEInterfaceOperationModel,
-    ComponentInterfaceDefinitionModel,
-    InterfaceOperationModel
-} from "../../../models/interfaceOperation";
+import {BEInterfaceOperationModel, InterfaceOperationModel} from "../../../models/interfaceOperation";
 import {AttributeBEModel} from "../../../models/attributes-outputs/attribute-be-model";
 import {InstanceAttributesAPIMap} from "../../../models/attributes-outputs/attribute-fe-map";
 
@@ -169,6 +159,10 @@ export class TopologyTemplateService {
         return this.getComponentDataByFieldsName(componentType, componentUniqueId, [COMPONENT_FIELDS.COMPONENT_PROPERTIES]);
     }
 
+    findAllComponentAttributes(componentType: string, componentUniqueId: string): Observable<ComponentGenericResponse> {
+        return this.getComponentDataByFieldsName(componentType, componentUniqueId, [COMPONENT_FIELDS.COMPONENT_ATTRIBUTES]);
+    }
+
     getCapabilitiesAndRequirements(componentType: string, componentId: string): Observable<ComponentGenericResponse> {
         return this.getComponentDataByFieldsName(componentType, componentId, [COMPONENT_FIELDS.COMPONENT_REQUIREMENTS, COMPONENT_FIELDS.COMPONENT_CAPABILITIES]);
     }
@@ -393,7 +387,7 @@ export class TopologyTemplateService {
     }
 
     updateProperty = (componentType: string, componentId: string, property: PropertyModel): Observable<PropertyModel> => {
-        var propertiesList:PropertyBEModel[]  = [property];
+        const propertiesList: PropertyBEModel[] = [property];
         return this.http.put<PropertyModel>(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/properties', propertiesList)
         .map((response) => {
             return new PropertyModel(response[Object.keys(response)[0]]);
@@ -470,6 +464,10 @@ export class TopologyTemplateService {
         return this.getComponentDataByFieldsName(componentType, componentId, [COMPONENT_FIELDS.COMPONENT_INSTANCES_PROPERTIES]);
     }
 
+    findAllComponentInstanceAttributes(componentType: string, componentId: string): Observable<ComponentGenericResponse> {
+        return this.getComponentDataByFieldsName(componentType, componentId, [COMPONENT_FIELDS.COMPONENT_INSTANCES_ATTRIBUTES]);
+    }
+
     getComponentInstanceCapabilityProperties(componentType: string, componentId: string): Observable<ComponentGenericResponse> {
         return this.getComponentDataByFieldsName(componentType, componentId,
             [COMPONENT_FIELDS.COMPONENT_CAPABILITIES, COMPONENT_FIELDS.COMPONENT_CAPABILITIES_PROPERTIES]);
index 238e099..96e01db 100644 (file)
   "TOSCA_FUNCTION_MODAL_TITLE": "Set value using TOSCA functions",
   "INPUT_DROPDOWN_LABEL": "Input",
   "TOSCA_FUNCTION_PROPERTY_DROPDOWN_LABEL": "Property",
+  "TOSCA_FUNCTION_ATTRIBUTE_DROPDOWN_LABEL": "Attribute",
   "TOSCA_FUNCTION_NO_INPUT_FOUND": "No input found with type {{type}}",
   "TOSCA_FUNCTION_NO_PROPERTY_FOUND": "No property found with type {{type}}",
+  "TOSCA_FUNCTION_NO_ATTRIBUTE_FOUND": "No attribute found with type {{type}}",
   "=========== AUTOMATED UPGRADE ===========": "",
   "RESOURCE_UPGRADE_TITLE": "Upgrade Services",
   "SERVICE_UPGRADE_TITLE": "Update Service References",
index adc2ad6..0741d68 100644 (file)
@@ -63,8 +63,8 @@ public class ToscaGetFunctionDataDefinition {
         }
 
         final var gson = new Gson();
-        if (functionType == ToscaGetFunctionType.GET_PROPERTY) {
-            return gson.toJson(buildGetPropertyFunctionValue());
+        if (functionType == ToscaGetFunctionType.GET_PROPERTY || functionType == ToscaGetFunctionType.GET_ATTRIBUTE) {
+            return gson.toJson(buildFunctionValueWithPropertySource());
         }
         if (functionType == ToscaGetFunctionType.GET_INPUT) {
             return gson.toJson(buildGetInputFunctionValue());
@@ -73,9 +73,11 @@ public class ToscaGetFunctionDataDefinition {
         throw new UnsupportedOperationException(String.format("ToscaGetFunctionType '%s' is not supported yet", functionType));
     }
 
-    private Map<String, Object> buildGetPropertyFunctionValue() {
+    private Map<String, Object> buildFunctionValueWithPropertySource() {
         if (propertySource == null) {
-            throw new IllegalStateException("propertySource is required in order to generate the get_property value");
+            throw new IllegalStateException(
+                String.format("propertySource is required in order to generate the %s value", functionType.getFunctionName())
+            );
         }
         if (propertySource == PropertySource.SELF) {
             return Map.of(functionType.getFunctionName(),
@@ -84,7 +86,9 @@ public class ToscaGetFunctionDataDefinition {
         }
         if (propertySource == PropertySource.INSTANCE) {
             if (sourceName == null) {
-                throw new IllegalStateException("sourceName is required in order to generate the get_property from INSTANCE value");
+                throw new IllegalStateException(
+                    String.format("sourceName is required in order to generate the %s from INSTANCE value", functionType.getFunctionName())
+                );
             }
             return Map.of(functionType.getFunctionName(),
                 Stream.concat(Stream.of(sourceName), propertyPathFromSource.stream()).collect(Collectors.toList())
index 1c4a678..a199f5e 100644 (file)
 
 package org.openecomp.sdc.be.datatypes.elements;
 
-import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import com.google.gson.Gson;
 import java.util.List;
@@ -29,6 +32,8 @@ import java.util.Map;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.EnumSource;
 import org.openecomp.sdc.be.datatypes.enums.PropertySource;
 import org.openecomp.sdc.be.datatypes.tosca.ToscaGetFunctionType;
 
@@ -78,10 +83,10 @@ class ToscaGetFunctionDataDefinitionTest {
         assertEquals(value, toscaGetFunction.getPropertyPathFromSource());
     }
 
-    @Test
-    void generateValueForGetPropertyFromSelfTest() {
+    @ParameterizedTest
+    @EnumSource(value =  ToscaGetFunctionType.class, names = {"GET_ATTRIBUTE", "GET_PROPERTY"})
+    void generateValueForGetFunctionWithSelfAsSourceTest(final ToscaGetFunctionType toscaFunction) {
         //given
-        final ToscaGetFunctionType toscaFunction = ToscaGetFunctionType.GET_PROPERTY;
         final var toscaGetFunction = createGetFunction(toscaFunction, PropertySource.SELF, List.of("property"), null);
         //when
         String actualValue = toscaGetFunction.generatePropertyValue();
@@ -110,10 +115,10 @@ class ToscaGetFunctionDataDefinitionTest {
         assertEquals(expectedGetPropertyValue, actualGetPropertyValue);
     }
 
-    @Test
-    void generateValueForGetPropertyFromInstanceTest() {
+    @ParameterizedTest
+    @EnumSource(value =  ToscaGetFunctionType.class, names = {"GET_ATTRIBUTE", "GET_PROPERTY"})
+    void generateValueForGetFunctionWithInstanceAsSourceTest(final ToscaGetFunctionType toscaFunction) {
         //given
-        final ToscaGetFunctionType toscaFunction = ToscaGetFunctionType.GET_PROPERTY;
         final var toscaGetFunction = createGetFunction(toscaFunction, PropertySource.INSTANCE, List.of("property"), "sourceName");
         //when
         String actualValue = toscaGetFunction.generatePropertyValue();