Service Consumption BE 57/82557/1
authorojasdubey <ojas.dubey@amdocs.com>
Mon, 18 Mar 2019 06:25:56 +0000 (11:55 +0530)
committerojasdubey <ojas.dubey@amdocs.com>
Mon, 18 Mar 2019 06:48:42 +0000 (12:18 +0530)
1. Service consumption feature
backend implementation
2. Operation output bug fix for
delete operation not allowed for
mapped operation output

Change-Id: Ib2554eed4f940b003955263a0c8bf795a23cac9a
Issue-ID: SDC-1990
Signed-off-by: ojasdubey <ojas.dubey@amdocs.com>
50 files changed:
asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/tasks/mig1902/InterfaceOperationMigration.java [new file with mode: 0644]
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogic.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InterfaceOperationBusinessLogic.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/PropertyBusinessLogic.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceInputsRedeclareHandler.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceInterfacesMerge.java [new file with mode: 0644]
catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceMergeDataBusinessLogic.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/DataForMergeHolder.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/property/DefaultPropertyDeclarator.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/InterfaceOperationUtils.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/InterfaceOperationValidation.java
catalog-be/src/main/java/org/openecomp/sdc/be/datamodel/utils/UiComponentDataConverter.java
catalog-be/src/main/java/org/openecomp/sdc/be/impl/ComponentsUtils.java
catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceConsumptionServlet.java [new file with mode: 0644]
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/InterfacesOperationsToscaUtil.java
catalog-be/src/main/java/org/openecomp/sdc/be/types/ServiceConsumptionData.java [new file with mode: 0644]
catalog-be/src/main/java/org/openecomp/sdc/be/types/ServiceConsumptionSource.java [new file with mode: 0644]
catalog-be/src/main/resources/config/error-configuration.yaml
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/InterfaceOperationBusinessLogicTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceInputsRedeclareHandlerTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceInterfacesMergeTest.java [new file with mode: 0644]
catalog-be/src/test/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceMergeDataBusinessLogicTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/property/ComponentInstancePropertyDeclaratorTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/utils/ComponentBuilder.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/utils/InterfaceOperationUtilsTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/validation/InterfaceOperationValidationTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/tosca/ToscaExportHandlerTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/tosca/utils/InterfacesOperationsToscaUtilTest.java
catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java
catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/types/EdgeLabelEnum.java
catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/types/VertexTypeEnum.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstance.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentParametersView.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/datamodel/TopologyTemplate.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTemplateOperation.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/TopologyTemplateOperation.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacade.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/utils/ModelConverter.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/InterfaceLifecycleOperation.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/ToscaFunctions.java
catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/UiComponentDataTransfer.java
catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/UiResourceDataTransfer.java
common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/MapInterfaceDataDefinition.java [new file with mode: 0644]
common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/OperationInputDefinition.java
common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/ComponentFieldsEnum.java
common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFields.java
common-be/src/test/java/org/openecomp/sdc/be/datatypes/elements/OperationInputDefinitionTest.java

diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/tasks/mig1902/InterfaceOperationMigration.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/tasks/mig1902/InterfaceOperationMigration.java
new file mode 100644 (file)
index 0000000..afbd3b4
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * 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.
+ */
+
+package org.openecomp.sdc.asdctool.migration.tasks.mig1902;
+
+import fj.data.Either;
+import java.math.BigInteger;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.openecomp.sdc.asdctool.migration.core.DBVersion;
+import org.openecomp.sdc.asdctool.migration.core.task.Migration;
+import org.openecomp.sdc.asdctool.migration.core.task.MigrationResult;
+import org.openecomp.sdc.be.config.ConfigurationManager;
+import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
+import org.openecomp.sdc.be.dao.jsongraph.TitanDao;
+import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
+import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
+import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
+import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
+import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.MapInterfaceDataDefinition;
+import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
+import org.openecomp.sdc.be.model.User;
+import org.openecomp.sdc.be.model.jsontitan.operations.InterfaceOperation;
+import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
+import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
+import org.openecomp.sdc.be.model.operations.impl.UserAdminOperation;
+import org.openecomp.sdc.common.log.wrappers.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+
+@org.springframework.stereotype.Component
+public class InterfaceOperationMigration implements Migration {
+
+    private static final Logger LOGGER = Logger.getLogger(InterfaceOperationMigration.class);
+
+    @Autowired
+    private TitanDao titanDao;
+    @Autowired
+    private UserAdminOperation userAdminOperation;
+    @Autowired
+    private InterfaceOperation interfaceOperation;
+
+    @Override
+    public String description() {
+        return "Update interface operation data to latest data model";
+    }
+
+    @Override
+    public DBVersion getVersion() {
+        return DBVersion.from(BigInteger.valueOf(1902), BigInteger.valueOf(0));
+    }
+
+    @Override
+    public MigrationResult migrate() {
+        final String userId = ConfigurationManager.getConfigurationManager().getConfiguration().getAutoHealingOwner();
+
+        Either<User, ActionStatus> userData = userAdminOperation.getUserData(userId, false);
+        if (userData.isRight()) {
+            return MigrationResult.error(
+                    "failed to update interface operation data. Failed to resolve user : "
+                            + userId + " error " + userData.right().value());
+        }
+
+        StorageOperationStatus status = getAndUpdateAllComponents();
+        return status == StorageOperationStatus.OK ? MigrationResult.success()
+                : MigrationResult.error("failed to update interface operation data . Error : " + status);
+    }
+
+    private StorageOperationStatus getAndUpdateAllComponents(){
+        Map<GraphPropertyEnum, Object> hasNotProps = new EnumMap<>(GraphPropertyEnum.class);
+        hasNotProps.put(GraphPropertyEnum.IS_DELETED, true);
+        return titanDao.getByCriteria(VertexTypeEnum.TOPOLOGY_TEMPLATE, null, hasNotProps, JsonParseFlagEnum.ParseAll)
+                .either(this::updateComponentVertices, this::handleError);
+    }
+
+    private StorageOperationStatus updateComponentVertices(List<GraphVertex> containersV) {
+        StorageOperationStatus status = StorageOperationStatus.OK;
+        for (GraphVertex container : containersV) {
+            status = updateDataOnGraph(container);
+            if (status != StorageOperationStatus.OK) {
+                break;
+            }
+        }
+        return status;
+    }
+
+    private StorageOperationStatus handleError(TitanOperationStatus err) {
+        titanDao.rollback();
+        return DaoStatusConverter.convertTitanStatusToStorageStatus(
+                TitanOperationStatus.NOT_FOUND == err ? TitanOperationStatus.OK : err);
+    }
+
+    private StorageOperationStatus updateDataOnGraph(GraphVertex componentVertex) {
+        try {
+            Either<GraphVertex, TitanOperationStatus> interfaceVertexEither =
+                    titanDao.getChildVertex(componentVertex, EdgeLabelEnum.INTERFACE, JsonParseFlagEnum.ParseJson);
+            if (interfaceVertexEither.isLeft()) {
+                GraphVertex interfaceVertex = interfaceVertexEither.left().value();
+                Map<String, InterfaceDataDefinition> interfaceDefinitions = (Map<String, InterfaceDataDefinition>) interfaceVertex.getJson();
+                if(MapUtils.isNotEmpty(interfaceDefinitions)){
+                    for (Map.Entry<String, InterfaceDataDefinition> interfaceDefinition : interfaceDefinitions.entrySet()) {
+                        if (StringUtils.isEmpty(interfaceDefinition.getValue().getType())) {
+                            interfaceDefinition.getValue().setType(interfaceDefinition.getValue().getToscaResourceName());
+                        }
+                    }
+                    interfaceVertex.setJson(interfaceDefinitions);
+                    Either<GraphVertex, TitanOperationStatus> updateInterfaceVertexEither = titanDao.updateVertex(interfaceVertex);
+                    if(updateInterfaceVertexEither.isRight()){
+                        return DaoStatusConverter.convertTitanStatusToStorageStatus(updateInterfaceVertexEither.right().value());
+                    }
+                }
+
+                StorageOperationStatus statusRes = interfaceOperation.removeToscaDataVertex(
+                        interfaceVertex, EdgeLabelEnum.INTERFACE_OPERATION, VertexTypeEnum.INTERFACE_OPERATION);
+                if (statusRes != StorageOperationStatus.NOT_FOUND && statusRes != StorageOperationStatus.OK) {
+                    return statusRes;
+                }
+            }
+
+            Either<GraphVertex, TitanOperationStatus> instInterfaceVertexEither =
+                    titanDao.getChildVertex(componentVertex, EdgeLabelEnum.INST_INTERFACES, JsonParseFlagEnum.ParseJson);
+            if (instInterfaceVertexEither.isLeft()) {
+                GraphVertex instInterfaceVertex = instInterfaceVertexEither.left().value();
+                Map<String, MapInterfaceDataDefinition> instInterfaceDefinitions = (Map<String, MapInterfaceDataDefinition>) instInterfaceVertex.getJson();
+                if(MapUtils.isNotEmpty(instInterfaceDefinitions)){
+                    for (Map.Entry<String, MapInterfaceDataDefinition> mapInstInterfaceDataDefinitions : instInterfaceDefinitions.entrySet()) {
+                        for (Map.Entry<String, InterfaceDataDefinition> instInterfaceDataDefinitions : mapInstInterfaceDataDefinitions.getValue().getMapToscaDataDefinition().entrySet()) {
+                            if (StringUtils.isEmpty(instInterfaceDataDefinitions.getValue().getType())) {
+                                instInterfaceDataDefinitions.getValue().setType(instInterfaceDataDefinitions.getValue().getToscaResourceName());
+                            }
+                        }
+                    }
+                    instInterfaceVertex.setJson(instInterfaceDefinitions);
+                    Either<GraphVertex, TitanOperationStatus> updateInstInterfaceVertexEither = titanDao.updateVertex(instInterfaceVertex);
+                    if(updateInstInterfaceVertexEither.isRight()){
+                        return DaoStatusConverter.convertTitanStatusToStorageStatus(updateInstInterfaceVertexEither.right().value());
+                    }
+                }
+            }
+
+            titanDao.commit();
+        } catch (Exception e) {
+            LOGGER.debug("Interface operation migration failed with error : ", e);
+            titanDao.rollback();
+            return StorageOperationStatus.GENERAL_ERROR;
+        }
+
+        return StorageOperationStatus.OK;
+    }
+}
\ No newline at end of file
index dfdae9b..d9a0c46 100644 (file)
@@ -332,6 +332,9 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
 
         resourceInstance.setProperties(ProxyServicePropertiesUtils.getProperties(service));
 
+        List<InputDefinition> serviceInputs = service.getInputs();
+        resourceInstance.setInputs(serviceInputs);
+
         String name = service.getNormalizedName() + ToscaOperationFacade.PROXY_SUFFIX;
         String toscaResourceName = ((Resource) proxyTemplate).getToscaResourceName();
         int lastIndexOf = toscaResourceName.lastIndexOf('.');
index 8a111f3..357eb14 100644 (file)
 
 package org.openecomp.sdc.be.components.impl;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
 import fj.data.Either;
 import org.openecomp.sdc.be.components.property.PropertyDeclarationOrchestrator;
 import org.openecomp.sdc.be.components.validation.ComponentValidations;
@@ -30,7 +37,13 @@ import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
-import org.openecomp.sdc.be.model.*;
+import org.openecomp.sdc.be.model.ComponentInstInputsMap;
+import org.openecomp.sdc.be.model.ComponentInstance;
+import org.openecomp.sdc.be.model.ComponentInstanceInput;
+import org.openecomp.sdc.be.model.ComponentInstanceProperty;
+import org.openecomp.sdc.be.model.ComponentParametersView;
+import org.openecomp.sdc.be.model.DataTypeDefinition;
+import org.openecomp.sdc.be.model.InputDefinition;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
@@ -40,8 +53,6 @@ import org.openecomp.sdc.exception.ResponseFormat;
 import org.springframework.stereotype.Component;
 
 import javax.inject.Inject;
-import java.util.*;
-import java.util.stream.Collectors;
 
 @Component("inputsBusinessLogic")
 public class InputsBusinessLogic extends BaseBusinessLogic {
@@ -279,6 +290,7 @@ public class InputsBusinessLogic extends BaseBusinessLogic {
                     return Either.right(updateInputObjectValue.right().value());
                 }
                 String newValue = updateInputObjectValue.left().value();
+                currInput.setValue(newValue);
                 currInput.setDefaultValue(newValue);
                 currInput.setOwnerId(userId);
                 Either<InputDefinition, StorageOperationStatus> status = toscaOperationFacade.updateInputOfComponent(component, currInput);
index 2fb7b0f..71d79e0 100644 (file)
 
 package org.openecomp.sdc.be.components.impl;
 
-import fj.data.Either;
+import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.createMappedInputPropertyDefaultValue;
+import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.createMappedOutputDefaultValue;
+import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.getInterfaceDefinitionFromComponentByInterfaceId;
+import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.getInterfaceDefinitionFromComponentByInterfaceType;
+import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.getOperationFromInterfaceDefinition;
+import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.isOperationInputMappedToComponentInput;
+import static org.openecomp.sdc.be.tosca.utils.InterfacesOperationsToscaUtil.SELF;
+
+import com.google.gson.Gson;
+
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -29,14 +37,21 @@ import java.util.Objects;
 import java.util.Optional;
 import java.util.UUID;
 import java.util.stream.Collectors;
-import org.openecomp.sdc.be.components.utils.InterfaceOperationUtils;
+
+import fj.data.Either;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.MapUtils;
 import org.openecomp.sdc.be.components.validation.InterfaceOperationValidation;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
 import org.openecomp.sdc.be.dao.cassandra.ArtifactCassandraDao;
 import org.openecomp.sdc.be.dao.cassandra.CassandraOperationStatus;
+import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
 import org.openecomp.sdc.be.model.ArtifactDefinition;
+import org.openecomp.sdc.be.model.ComponentInstanceInterface;
+import org.openecomp.sdc.be.model.InputDefinition;
 import org.openecomp.sdc.be.model.InterfaceDefinition;
 import org.openecomp.sdc.be.model.Operation;
 import org.openecomp.sdc.be.model.User;
@@ -83,9 +98,8 @@ public class InterfaceOperationBusinessLogic extends BaseBusinessLogic {
         }
 
         try {
-            Optional<InterfaceDefinition> optionalInterface = InterfaceOperationUtils
-                                                                      .getInterfaceDefinitionFromComponentByInterfaceId(
-                                                                              storedComponent, interfaceId);
+            Optional<InterfaceDefinition> optionalInterface = getInterfaceDefinitionFromComponentByInterfaceId(
+                    storedComponent, interfaceId);
             if (!optionalInterface.isPresent()) {
                 return Either.right(
                         componentsUtils.getResponseFormat(ActionStatus.INTERFACE_NOT_FOUND_IN_COMPONENT, interfaceId));
@@ -95,13 +109,19 @@ public class InterfaceOperationBusinessLogic extends BaseBusinessLogic {
             Map<String, Operation> operationsCollection = new HashMap<>();
             for (String operationId : operationsToDelete) {
                 Optional<Map.Entry<String, Operation>> optionalOperation =
-                        InterfaceOperationUtils.getOperationFromInterfaceDefinition(interfaceDefinition, operationId);
+                        getOperationFromInterfaceDefinition(interfaceDefinition, operationId);
                 if (!optionalOperation.isPresent()) {
                     return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND,
                             storedComponent.getUniqueId()));
                 }
 
                 Operation storedOperation = optionalOperation.get().getValue();
+                Either<Boolean, ResponseFormat> validateDeleteOperationContainsNoMappedOutputResponse =
+                        interfaceOperationValidation.validateDeleteOperationContainsNoMappedOutput(storedOperation,
+                                storedComponent, interfaceDefinition);
+                if (validateDeleteOperationContainsNoMappedOutputResponse.isRight()) {
+                    return Either.right(validateDeleteOperationContainsNoMappedOutputResponse.right().value());
+                }
                 String artifactUuId = storedOperation.getImplementation().getArtifactUUID();
                 CassandraOperationStatus cassandraStatus = artifactCassandraDao.deleteArtifact(artifactUuId);
                 if (cassandraStatus != CassandraOperationStatus.OK) {
@@ -190,9 +210,8 @@ public class InterfaceOperationBusinessLogic extends BaseBusinessLogic {
         }
 
         try {
-            Optional<InterfaceDefinition> optionalInterface = InterfaceOperationUtils
-                                                                      .getInterfaceDefinitionFromComponentByInterfaceId(
-                                                                              storedComponent, interfaceId);
+            Optional<InterfaceDefinition> optionalInterface = getInterfaceDefinitionFromComponentByInterfaceId(
+                    storedComponent, interfaceId);
             if (!optionalInterface.isPresent()) {
                 return Either.right(
                         componentsUtils.getResponseFormat(ActionStatus.INTERFACE_NOT_FOUND_IN_COMPONENT, interfaceId));
@@ -201,7 +220,7 @@ public class InterfaceOperationBusinessLogic extends BaseBusinessLogic {
 
             for (String operationId : operationsToGet) {
                 Optional<Map.Entry<String, Operation>> optionalOperation =
-                        InterfaceOperationUtils.getOperationFromInterfaceDefinition(interfaceDefinition, operationId);
+                        getOperationFromInterfaceDefinition(interfaceDefinition, operationId);
                 if (!optionalOperation.isPresent()) {
                     return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND,
                             storedComponent.getUniqueId()));
@@ -257,7 +276,7 @@ public class InterfaceOperationBusinessLogic extends BaseBusinessLogic {
             Map<String, Operation> operationsCollection = new HashMap<>();
             for (InterfaceDefinition inputInterfaceDefinition : interfaceDefinitions) {
                 Optional<InterfaceDefinition> optionalInterface =
-                        InterfaceOperationUtils.getInterfaceDefinitionFromComponentByInterfaceType(
+                        getInterfaceDefinitionFromComponentByInterfaceType(
                                 storedComponent, inputInterfaceDefinition.getType());
                 Either<Boolean, ResponseFormat> interfaceOperationValidationResponseEither =
                         interfaceOperationValidation
@@ -287,7 +306,7 @@ public class InterfaceOperationBusinessLogic extends BaseBusinessLogic {
                         addOperationToInterface(interfaceDef, operation);
                     } else {
                         Optional<Map.Entry<String, Operation>> optionalOperation =
-                                InterfaceOperationUtils.getOperationFromInterfaceDefinition(interfaceDef,
+                                getOperationFromInterfaceDefinition(interfaceDef,
                                         operation.getUniqueId());
                         if (!optionalOperation.isPresent()) {
                             titanDao.rollback();
@@ -364,31 +383,53 @@ public class InterfaceOperationBusinessLogic extends BaseBusinessLogic {
             InterfaceDefinition storedInterfaceDef) {
         if (storedInterfaceDef != null) {
             return Either.left(storedInterfaceDef);
-        } else {
-            interfaceDefinition.setUniqueId(UUID.randomUUID().toString());
-            interfaceDefinition.setToscaResourceName(interfaceDefinition.getType());
-            Either<List<InterfaceDefinition>, StorageOperationStatus> interfaceCreateEither =
-                    interfaceOperation.addInterfaces(component.getUniqueId(),
-                            Collections.singletonList(interfaceDefinition));
-            if (interfaceCreateEither.isRight()) {
-                titanDao.rollback();
-                return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(
-                        interfaceCreateEither.right().value(), component.getComponentType())));
-            }
-            return Either.left(interfaceCreateEither.left().value().get(0));
         }
+        interfaceDefinition.setUniqueId(UUID.randomUUID().toString());
+        interfaceDefinition.setToscaResourceName(interfaceDefinition.getType());
+        Either<List<InterfaceDefinition>, StorageOperationStatus> interfaceCreateEither =
+                interfaceOperation.addInterfaces(component.getUniqueId(),
+                        Collections.singletonList(interfaceDefinition));
+        if (interfaceCreateEither.isRight()) {
+            titanDao.rollback();
+            return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(
+                    interfaceCreateEither.right().value(), component.getComponentType())));
+        }
+        return Either.left(interfaceCreateEither.left().value().get(0));
     }
 
     private void updateOperationInputDefs(org.openecomp.sdc.be.model.Component component,
-            Collection<Operation> interfaceOperations) {
+                                          Collection<Operation> interfaceOperations) {
         interfaceOperations.stream().filter(operation -> Objects.nonNull(operation.getInputs())).forEach(
                 operation -> operation.getInputs().getListToscaDataDefinition().forEach(
-                        inp -> component.getInputs().stream().filter(in -> inp.getInputId().equals(in.getUniqueId()))
-                                       .forEach(in -> {
-                                           inp.setDefaultValue(in.getDefaultValue());
-                                           inp.setValue(in.getValue());
-                                           inp.setSchema(in.getSchema());
-                                       })));
+                        inp -> component.getInputs()
+                                .forEach(in -> updateOperationInputDefinition(component, inp, in))));
+    }
+
+    private void updateOperationInputDefinition(org.openecomp.sdc.be.model.Component component,
+                                                OperationInputDefinition operationInput,
+                                                InputDefinition componentInput) {
+        if (operationInput.getInputId().equals(componentInput.getUniqueId())) {
+            //Set the default value, value and schema only for inputs mapped to component inputs
+            operationInput.setDefaultValue(componentInput.getDefaultValue());
+            operationInput.setToscaDefaultValue(getInputToscaDefaultValue(operationInput, component));
+            operationInput.setValue(componentInput.getValue());
+            operationInput.setSchema(componentInput.getSchema());
+        }
+        //Set the tosca default value for inputs mapped to component inputs as well as other outputs
+        operationInput.setToscaDefaultValue(getInputToscaDefaultValue(operationInput, component));
+    }
+
+    private String getInputToscaDefaultValue(OperationInputDefinition input,
+                                             org.openecomp.sdc.be.model.Component component) {
+        Map<String, List<String>> defaultInputValue;
+        if (isOperationInputMappedToComponentInput(input, component.getInputs())) {
+            String propertyName = input.getInputId().substring(input.getInputId().indexOf('.') + 1);
+            defaultInputValue = createMappedInputPropertyDefaultValue(propertyName);
+        } else {
+            //Currently inputs can only be mapped to a declared input or an other operation outputs
+            defaultInputValue = createMappedOutputDefaultValue(SELF, input.getInputId());
+        }
+        return new Gson().toJson(defaultInputValue);
     }
 
     private void addOperationToInterface(InterfaceDefinition interfaceDefinition, Operation interfaceOperation) {
@@ -420,4 +461,55 @@ public class InterfaceOperationBusinessLogic extends BaseBusinessLogic {
                 UPDATE_INTERFACE_OPERATION, lock);
     }
 
+    public Either<List<OperationInputDefinition>, ResponseFormat> getInputsListForOperation(String componentId,
+                                                                                            String componentInstanceId, String interfaceId, String operationId, User user) {
+        Either<org.openecomp.sdc.be.model.Component, ResponseFormat> componentEither = getComponentDetails(componentId);
+        if (componentEither.isRight()){
+            return Either.right(componentEither.right().value());
+        }
+
+        org.openecomp.sdc.be.model.Component storedComponent = componentEither.left().value();
+        validateUserExists(user.getUserId(), GET_INTERFACE_OPERATION, true);
+
+        Either<Boolean, ResponseFormat> lockResult = lockComponentResult(true, storedComponent, GET_INTERFACE_OPERATION);
+        if (lockResult.isRight()) {
+            return Either.right(lockResult.right().value());
+        }
+
+        try{
+            org.openecomp.sdc.be.model.Component parentComponent = componentEither.left().value();
+            Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces =
+                    parentComponent.getComponentInstancesInterfaces();
+            if(MapUtils.isEmpty(componentInstanceInterfaces)) {
+                return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND,
+                        componentInstanceId));
+            }
+
+            List<ComponentInstanceInterface> componentInstanceInterfaceList =
+                    componentInstanceInterfaces.get(componentInstanceId);
+            for(ComponentInstanceInterface componentInstanceInterface : componentInstanceInterfaceList) {
+                if(componentInstanceInterface.getInterfaceId().equals(interfaceId)){
+                    Map<String, OperationDataDefinition> operations = componentInstanceInterface.getOperations();
+                    if(MapUtils.isNotEmpty(operations) && operations.containsKey(operationId)) {
+                        ListDataDefinition<OperationInputDefinition> inputs = operations.get(operationId).getInputs();
+                        return Either.left(CollectionUtils.isEmpty(inputs.getListToscaDataDefinition())
+                                ? new ArrayList<>() : inputs.getListToscaDataDefinition());
+                    }
+                }
+            }
+            return Either.left(new ArrayList<>());
+        }
+        catch (Exception e) {
+            LOGGER.error(EXCEPTION_OCCURRED_DURING_INTERFACE_OPERATION, "get", e);
+            titanDao.rollback();
+            return Either.right(componentsUtils.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NOT_FOUND));
+        }
+        finally {
+            if (lockResult.isLeft() && lockResult.left().value()) {
+                graphLockOperation.unlockComponent(storedComponent.getUniqueId(),
+                        NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue()));
+            }
+        }
+    }
+
 }
index 0439dd5..3c49e21 100644 (file)
@@ -28,10 +28,20 @@ import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.openecomp.sdc.be.config.BeEcompErrorManager;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
-import org.openecomp.sdc.be.datatypes.elements.*;
+import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
+import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
-import org.openecomp.sdc.be.model.*;
+import org.openecomp.sdc.be.model.Component;
+import org.openecomp.sdc.be.model.ComponentInstanceInterface;
+import org.openecomp.sdc.be.model.ComponentParametersView;
+import org.openecomp.sdc.be.model.DataTypeDefinition;
+import org.openecomp.sdc.be.model.IComplexDefaultValue;
+import org.openecomp.sdc.be.model.InterfaceDefinition;
+import org.openecomp.sdc.be.model.PropertyDefinition;
 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
 import org.openecomp.sdc.be.model.operations.utils.ComponentValidationUtils;
@@ -377,7 +387,8 @@ public class PropertyBusinessLogic extends BaseBusinessLogic {
             return Optional.empty();
         }
 
-        return operationInputsList.stream().filter(input -> input.getInputId().equals(propertyDefinition.getUniqueId())).findAny();
+        return operationInputsList.stream().filter(input -> input.getInputId().equals(propertyDefinition.getUniqueId())
+                || (input.getSourceProperty() != null && input.getSourceProperty().equals(propertyDefinition.getUniqueId()))).findAny();
     }
 
     /**
index dfe1467..65b1f12 100644 (file)
@@ -25,6 +25,7 @@ import com.google.common.base.Strings;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 import fj.data.Either;
+import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.ImmutablePair;
@@ -36,6 +37,7 @@ import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
 import org.openecomp.sdc.be.components.impl.utils.NodeFilterConstraintAction;
 import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction;
 import org.openecomp.sdc.be.components.path.ForwardingPathValidator;
+import org.openecomp.sdc.be.components.utils.InterfaceOperationUtils;
 import org.openecomp.sdc.be.components.validation.NodeFilterValidator;
 import org.openecomp.sdc.be.components.validation.ServiceDistributionValidation;
 import org.openecomp.sdc.be.config.BeEcompErrorManager;
@@ -47,9 +49,14 @@ import org.openecomp.sdc.be.datamodel.ServiceRelations;
 import org.openecomp.sdc.be.datamodel.utils.UiComponentDataConverter;
 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.ForwardingPathDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
+import org.openecomp.sdc.be.datatypes.elements.OperationOutputDefinition;
 import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterPropertyDataDefinition;
 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
 import org.openecomp.sdc.be.datatypes.enums.InstantiationTypes;
+import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
 import org.openecomp.sdc.be.externalapi.servlet.representation.ServiceDistributionReqInfo;
@@ -65,11 +72,16 @@ import org.openecomp.sdc.be.model.operations.api.IElementOperation;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
 import org.openecomp.sdc.be.model.operations.utils.ComponentValidationUtils;
+import org.openecomp.sdc.be.model.tosca.ToscaFunctions;
+import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
+import org.openecomp.sdc.be.model.tosca.validators.PropertyTypeValidator;
 import org.openecomp.sdc.be.resources.data.ComponentInstanceData;
 import org.openecomp.sdc.be.resources.data.ComponentMetadataData;
 import org.openecomp.sdc.be.resources.data.auditing.*;
 import org.openecomp.sdc.be.resources.data.auditing.model.ResourceCommonInfo;
 import org.openecomp.sdc.be.resources.data.auditing.model.ResourceVersionInfo;
+import org.openecomp.sdc.be.types.ServiceConsumptionData;
+import org.openecomp.sdc.be.types.ServiceConsumptionSource;
 import org.openecomp.sdc.be.ui.model.UiComponentDataTransfer;
 import org.openecomp.sdc.be.user.Role;
 import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum;
@@ -83,6 +95,7 @@ import org.openecomp.sdc.common.util.ThreadLocalsHolder;
 import org.openecomp.sdc.common.util.ValidationUtils;
 import org.openecomp.sdc.exception.ResponseFormat;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
 import org.springframework.web.context.WebApplicationContext;
 
 import javax.servlet.ServletContext;
@@ -95,7 +108,12 @@ import java.util.stream.Collectors;
 
 import static org.apache.commons.collections.CollectionUtils.isEmpty;
 import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
+import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.getOperationOutputName;
+import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.isOperationInputMappedToOtherOperationOutput;
 import static org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum.UPDATE_SERVICE_METADATA;
+import static org.openecomp.sdc.be.tosca.utils.InterfacesOperationsToscaUtil.SELF;
+import static org.openecomp.sdc.be.types.ServiceConsumptionSource.SERVICE_INPUT;
+import static org.openecomp.sdc.be.types.ServiceConsumptionSource.STATIC;
 
 @org.springframework.stereotype.Component("serviceBusinessLogic")
 public class ServiceBusinessLogic extends ComponentBusinessLogic {
@@ -227,6 +245,441 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic {
 
     }
 
+    public Either<List<Operation>, ResponseFormat> addServiceConsumptionData(String serviceId,
+                                                                             String serviceInstanceId,
+                                                                             String operationId,
+                                                                             List<ServiceConsumptionData> serviceConsumptionDataList,
+                                                                             String userId) {
+        List<Operation> operationList = new ArrayList<>();
+
+        Either<Service, StorageOperationStatus> serviceEither =
+                toscaOperationFacade.getToscaElement(serviceId);
+        if(serviceEither.isRight()) {
+            return Either.right(componentsUtils.getResponseFormat
+                    (serviceEither.right().value()));
+        }
+
+        Service service = serviceEither.left().value();
+
+
+        StorageOperationStatus storageOperationStatus =
+                graphLockOperation.lockComponent(service.getUniqueId(), NodeTypeEnum.Service);
+        if (storageOperationStatus != StorageOperationStatus.OK) {
+            return Either.right(componentsUtils.getResponseFormat(storageOperationStatus));
+        }
+
+        try {
+            for (ServiceConsumptionData serviceConsumptionData : serviceConsumptionDataList) {
+                Either<Operation, ResponseFormat> operationEither =
+                        addPropertyServiceConsumption(serviceId, serviceInstanceId, operationId,
+                                userId, serviceConsumptionData);
+
+                if (operationEither.isRight()) {
+                    return Either.right(operationEither.right().value());
+                }
+
+                operationList.add(operationEither.left().value());
+            }
+
+            titanDao.commit();
+            return Either.left(operationList);
+        } catch (Exception e) {
+            titanDao.rollback();
+            return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
+
+        } finally {
+            graphLockOperation.unlockComponent(service.getUniqueId(), NodeTypeEnum.Service);
+
+        }
+    }
+
+    public Either <Operation, ResponseFormat> addPropertyServiceConsumption(String serviceId,
+                                                                            String serviceInstanceId,
+                                                                            String operationId,
+                                                                            String userId,
+                                                                            ServiceConsumptionData serviceConsumptionData) {
+        validateUserExists(userId, "create Property", false);
+
+        Either<Service, StorageOperationStatus> serviceEither =
+                toscaOperationFacade.getToscaElement(serviceId);
+        if(serviceEither.isRight()) {
+            return Either.right(componentsUtils.getResponseFormat(serviceEither.right
+                    ().value()));
+        }
+
+        Service parentService = serviceEither.left().value();
+
+        List<ComponentInstance> componentInstances = parentService.getComponentInstances();
+        if(CollectionUtils.isEmpty(componentInstances)) {
+            return Either.right(componentsUtils.getResponseFormat(ActionStatus
+                    .INTERFACE_OPERATION_NOT_FOUND, serviceInstanceId));
+        }
+
+        Optional<ComponentInstance> serviceInstanceCandidate =
+                componentInstances.stream().filter(instance -> instance.getUniqueId().equals
+                        (serviceInstanceId)).findAny();
+
+        if(!serviceInstanceCandidate.isPresent()) {
+            return Either.right(componentsUtils.getResponseFormat(ActionStatus
+                    .INTERFACE_OPERATION_NOT_FOUND, serviceInstanceId));
+        }
+
+        Map<String, List<ComponentInstanceInterface>> componentInstancesInterfaces =
+                parentService.getComponentInstancesInterfaces();
+        if(MapUtils.isEmpty(componentInstancesInterfaces)) {
+            return Either.right(componentsUtils.getResponseFormat(ActionStatus
+                    .INTERFACE_OPERATION_NOT_FOUND, serviceInstanceId));
+        }
+
+        List<InterfaceDefinition> interfaces = new ArrayList<>();
+        for(ComponentInstanceInterface componentInstanceInterface :
+                componentInstancesInterfaces.get(serviceInstanceId)) {
+            interfaces.add(componentInstanceInterface);
+        }
+
+        ComponentInstance serviceInstance = serviceInstanceCandidate.get();
+        Optional<InterfaceDefinition> interfaceCandidate = InterfaceOperationUtils
+                .getInterfaceDefinitionFromOperationId(interfaces, operationId);
+
+        if(!interfaceCandidate.isPresent()) {
+            return Either.right(componentsUtils.getResponseFormat(ActionStatus
+                    .INTERFACE_OPERATION_NOT_FOUND, serviceInstanceId));
+        }
+
+        InterfaceDefinition interfaceDefinition = interfaceCandidate.get();
+        Map<String, Operation> operations = interfaceDefinition.getOperationsMap();
+        if(MapUtils.isEmpty(operations)) {
+            return Either.right(componentsUtils.getResponseFormat(ActionStatus
+                    .INTERFACE_OPERATION_NOT_FOUND, serviceInstanceId));
+        }
+
+        Operation operation = operations.get(operationId);
+        Either<Operation, ResponseFormat> operationEither = Either.left(operation);
+
+        ListDataDefinition<OperationInputDefinition> inputs = operation.getInputs();
+        Optional<OperationInputDefinition> inputCandidate =
+                getOperationInputByInputId(serviceConsumptionData, inputs);
+
+        if(!inputCandidate.isPresent()) {
+            return Either.right(new ResponseFormat(HttpStatus.NOT_FOUND.value()));
+        }
+
+        OperationInputDefinition operationInputDefinition = inputCandidate.get();
+
+        // add data to operation
+
+        if(Objects.nonNull(serviceConsumptionData.getValue()))  {
+            operationEither =
+                    handleConsumptionValue(parentService, serviceInstanceId, serviceConsumptionData, operation,
+                            operationInputDefinition);
+        }
+
+        if(operationEither.isRight()) {
+            return Either.right(operationEither.right().value());
+        }
+
+        Operation updatedOperation = operationEither.left().value();
+        operations.remove(operationId);
+        operations.put(operationId, updatedOperation);
+        interfaceDefinition.setOperationsMap(operations);
+
+        parentService.getComponentInstances().remove(serviceInstance);
+        if(CollectionUtils.isEmpty(parentService.getComponentInstances())) {
+            parentService.setComponentInstances(new ArrayList<>());
+        }
+
+        Map<String, Object> instanceInterfaces =
+                MapUtils.isEmpty(serviceInstance.getInterfaces())? new HashMap<>() : serviceInstance.getInterfaces();
+        instanceInterfaces.remove(interfaceDefinition.getUniqueId());
+        instanceInterfaces.put(interfaceDefinition.getUniqueId(), interfaceDefinition);
+        serviceInstance.setInterfaces(instanceInterfaces);
+
+        removeComponentInstanceInterfaceByInterfaceId(interfaceDefinition.getUniqueId(), componentInstancesInterfaces.get(serviceInstanceId));
+        componentInstancesInterfaces.get(serviceInstanceId).add(new ComponentInstanceInterface(interfaceDefinition.getUniqueId(), interfaceDefinition));
+
+        parentService.getComponentInstances().add(serviceInstance);
+
+        StorageOperationStatus status = toscaOperationFacade.updateComponentInstanceInterfaces(parentService, serviceInstanceId);
+
+        if(status != StorageOperationStatus.OK) {
+            return Either.right(componentsUtils.getResponseFormat(ActionStatus
+                    .INTERFACE_OPERATION_NOT_FOUND, serviceInstanceId));
+        }
+
+        return Either.left(operation);
+    }
+
+    private void removeComponentInstanceInterfaceByInterfaceId(String interfaceIdToRemove,
+                                                               List<ComponentInstanceInterface> instanceInterfaces) {
+        if(CollectionUtils.isEmpty(instanceInterfaces)) {
+            return;
+        }
+
+        Optional<ComponentInstanceInterface> interfaceToRemove =
+                instanceInterfaces.stream().filter(instInterface -> instInterface.getUniqueId().equals
+                        (interfaceIdToRemove)).findAny();
+
+        if(interfaceToRemove.isPresent()) {
+            instanceInterfaces.remove(interfaceToRemove.get());
+        }
+
+    }
+
+    private Either<Operation, ResponseFormat> handleConsumptionValue(Service containerService,
+                                                                     String serviceInstanceId,
+                                                                     ServiceConsumptionData serviceConsumptionData,
+                                                                     Operation operation,
+                                                                     OperationInputDefinition
+                                                                             operationInputDefinition) {
+        String source = serviceConsumptionData.getSource();
+        String consumptionValue = serviceConsumptionData.getValue();
+        String type = serviceConsumptionData.getType();
+        String operationIdentifier = consumptionValue.contains(".")
+                ? consumptionValue.substring(0, consumptionValue.lastIndexOf('.'))
+                : consumptionValue;
+
+        ServiceConsumptionSource sourceValue = ServiceConsumptionSource.getSourceValue(source);
+
+        if(STATIC.equals(sourceValue)) {
+            return handleConsumptionStaticValue(consumptionValue, type, operation,
+                    operationInputDefinition);
+        }
+
+        if (Objects.isNull(sourceValue)) {
+            List<PropertyDefinition> propertyDefinitions;
+            String componentName;
+            List<OperationOutputDefinition> outputs = null;
+            if (source.equals(containerService.getUniqueId())) {
+                Either<Service, StorageOperationStatus> serviceToTakePropEither =
+                        toscaOperationFacade.getToscaElement(source);
+                if (serviceToTakePropEither.isRight()) {
+                    return Either.right(componentsUtils.getResponseFormat(serviceToTakePropEither.right().value()));
+                }
+                Service service = serviceToTakePropEither.left().value();
+                operationInputDefinition.setSource(service.getUniqueId());
+                sourceValue = SERVICE_INPUT;
+                propertyDefinitions = service.getProperties();
+                componentName = service.getName();
+                outputs = InterfaceOperationUtils.getOtherOperationOutputsOfComponent(operationIdentifier,
+                        service.getInterfaces()).getListToscaDataDefinition();
+            } else {
+                Optional<ComponentInstance> getComponentInstance = containerService.getComponentInstanceById(source);
+                if(!getComponentInstance.isPresent()){
+                    return Either.right(componentsUtils.getResponseFormat(
+                            ActionStatus.COMPONENT_INSTANCE_NOT_FOUND_ON_CONTAINER, source));
+                }
+                ComponentInstance componentInstance = getComponentInstance.get();
+                operationInputDefinition.setSource(componentInstance.getUniqueId());
+                propertyDefinitions = componentInstance.getProperties();
+                componentName = source.equals(serviceInstanceId) ? SELF : componentInstance.getName();
+                if (MapUtils.isNotEmpty(componentInstance.getInterfaces())) {
+                    Map<String, InterfaceDataDefinition> componentInstanceInterfaces =
+                            componentInstance.getInterfaces().entrySet().stream()
+                                    .collect(Collectors.toMap((Map.Entry::getKey),
+                                            (interfaceEntry -> (InterfaceDataDefinition) interfaceEntry.getValue())));
+                    outputs = InterfaceOperationUtils.getOtherOperationOutputsOfComponent(operationIdentifier,
+                            componentInstanceInterfaces).getListToscaDataDefinition();
+                }
+            }
+
+            if(sourceValue == ServiceConsumptionSource.SERVICE_INPUT) {
+                //The operation input in service consumption has been mapped to an input in the parent service
+                return handleConsumptionInputValue(consumptionValue, containerService, operation,
+                        operationInputDefinition);
+            }
+            return handleConsumptionPropertyValue(operation, operationInputDefinition,
+                    serviceConsumptionData, propertyDefinitions, outputs, consumptionValue, componentName);
+        }
+
+        operationInputDefinition.setToscaPresentationValue(JsonPresentationFields.SOURCE, source);
+        operationInputDefinition.setSource(source);
+
+        return Either.left(operation);
+    }
+
+    private Optional<OperationInputDefinition> getOperationInputByInputId(ServiceConsumptionData serviceConsumptionData,
+                                                                          ListDataDefinition<OperationInputDefinition> inputs) {
+
+        if(CollectionUtils.isEmpty(inputs.getListToscaDataDefinition())) {
+            return Optional.empty();
+        }
+
+        return inputs.getListToscaDataDefinition().stream().filter(operationInput -> operationInput.getInputId().equals
+                (serviceConsumptionData.getInputId()))
+                .findAny();
+    }
+
+    private Either<Operation, ResponseFormat> handleConsumptionPropertyValue(
+            Operation operation, OperationInputDefinition operationInputDefinition,
+            ServiceConsumptionData serviceConsumptionData, List<PropertyDefinition> properties,
+            List<OperationOutputDefinition> outputs, String consumptionValue, String componentName) {
+
+        if (CollectionUtils.isEmpty(properties) && CollectionUtils.isEmpty(outputs)) {
+            return Either.left(operation);
+        }
+
+        if (CollectionUtils.isNotEmpty(outputs)
+                && isOperationInputMappedToOtherOperationOutput(getOperationOutputName(consumptionValue), outputs)) {
+            return handleConsumptionInputMappedToOperationOutput(operation, operationInputDefinition, outputs,
+                    consumptionValue, componentName);
+        }
+
+        if (CollectionUtils.isNotEmpty(properties)) {
+            return handleConsumptionInputMappedToProperty(operation, operationInputDefinition, serviceConsumptionData,
+                    properties, componentName);
+        }
+        return Either.left(operation);
+    }
+
+    private Either<Operation, ResponseFormat> handleConsumptionInputMappedToProperty(Operation operation,
+                                                                                     OperationInputDefinition operationInputDefinition, ServiceConsumptionData serviceConsumptionData,
+                                                                                     List<PropertyDefinition> properties, String componentName) {
+        Optional<PropertyDefinition> servicePropertyCandidate =
+                properties.stream().filter(property -> property.getName()
+                        .equals(serviceConsumptionData.getValue())).findAny();
+
+        if (servicePropertyCandidate.isPresent()) {
+            boolean isInputTypeSimilarToOperation =
+                    isAssignedValueFromValidType(operationInputDefinition.getType(),
+                            servicePropertyCandidate.get());
+
+            if (!isInputTypeSimilarToOperation) {
+                return Either.right(componentsUtils.getResponseFormat(
+                        ActionStatus.INVALID_CONSUMPTION_TYPE, operationInputDefinition.getType()));
+            }
+
+            addPropertyToInputValue(componentName, operation, operationInputDefinition,
+                    servicePropertyCandidate.get());
+        }
+        return Either.left(operation);
+    }
+
+    private Either<Operation, ResponseFormat> handleConsumptionInputMappedToOperationOutput(Operation operation,
+                                                                                            OperationInputDefinition operationInputDefinition, List<OperationOutputDefinition> outputs,
+                                                                                            String consumptionValue, String componentName) {
+        String outputName = getOperationOutputName(consumptionValue);
+        Optional<OperationOutputDefinition> servicePropertyOutputCandidate = outputs.stream()
+                .filter(output -> output.getName().equals(outputName)).findAny();
+        if (servicePropertyOutputCandidate.isPresent()) {
+            boolean isInputTypeSimilarToOperation =
+                    isAssignedValueFromValidType(operationInputDefinition.getType(),
+                            servicePropertyOutputCandidate.get());
+            if (!isInputTypeSimilarToOperation) {
+                return Either.right(componentsUtils.getResponseFormat(
+                        ActionStatus.INVALID_CONSUMPTION_TYPE, operationInputDefinition.getType()));
+            }
+            addOutputToInputValue(componentName, consumptionValue, operation, operationInputDefinition);
+        }
+        return Either.left(operation);
+    }
+
+    private void addPropertyToInputValue(String componentName, Operation operation,
+                                         OperationInputDefinition operationInputDefinition,
+                                         PropertyDefinition serviceProperty) {
+        Map<String, List<String>> getProperty = new HashMap<>();
+        List<String> getPropertyValues = new ArrayList<>();
+        getPropertyValues.add(componentName);
+        getPropertyValues.add(serviceProperty.getName());
+        getProperty.put(ToscaFunctions.GET_PROPERTY.getFunctionName(), getPropertyValues);
+
+        operationInputDefinition.setSourceProperty(serviceProperty.getUniqueId());
+        operation.getInputs().delete(operationInputDefinition);
+        operationInputDefinition.setToscaPresentationValue(JsonPresentationFields.GET_PROPERTY,
+                getPropertyValues);
+        operationInputDefinition.setValue((new Gson()).toJson(getProperty));
+        operation.getInputs().add(operationInputDefinition);
+    }
+
+    private void addOutputToInputValue(String componentName, String consumptionValue,
+                                       Operation operation, OperationInputDefinition operationInputDefinition) {
+        Map<String, List<String>> getOperationOutput =
+                InterfaceOperationUtils.createMappedOutputDefaultValue(componentName, consumptionValue);
+        operation.getInputs().delete(operationInputDefinition);
+        operationInputDefinition.setToscaPresentationValue(JsonPresentationFields.GET_OPERATION_OUTPUT,
+                getOperationOutput);
+        operationInputDefinition.setValue((new Gson()).toJson(getOperationOutput));
+        operation.getInputs().add(operationInputDefinition);
+    }
+
+    public Either<Operation, ResponseFormat> handleConsumptionStaticValue(String value, String type,
+                                                                          Operation operation,
+                                                                          OperationInputDefinition
+                                                                                  operationInputDefinition) {
+        boolean isInputTypeSimilarToOperation =
+                isAssignedValueFromValidType(type, value);
+
+        if(!isInputTypeSimilarToOperation) {
+            return Either.right(componentsUtils.getResponseFormat(
+                    ActionStatus.INVALID_CONSUMPTION_TYPE, type));
+        }
+        addStaticValueToInputOperation(value, operation, operationInputDefinition);
+
+        return Either.left(operation);
+    }
+
+    private void addStaticValueToInputOperation(String value, Operation operation,
+                                                OperationInputDefinition operationInputDefinition) {
+        operation.getInputs().delete(operationInputDefinition);
+        operationInputDefinition.setSource(STATIC.getSource());
+        operationInputDefinition.setSourceProperty(null);
+        operationInputDefinition.setValue(value);
+        operation.getInputs().add(operationInputDefinition);
+    }
+
+    private Either<Operation, ResponseFormat>  handleConsumptionInputValue(String inputId,
+                                                                           Service service,
+                                                                           Operation operation,
+                                                                           OperationInputDefinition
+                                                                                   operationInputDefinition) {
+        List<InputDefinition> serviceInputs = service.getInputs();
+        Optional<InputDefinition> inputForValue =
+                serviceInputs.stream().filter(input -> input.getUniqueId().contains(inputId)).findAny();
+
+        if(inputForValue.isPresent()) {
+            boolean isInputTypeSimilarToOperation =
+                    isAssignedValueFromValidType(operationInputDefinition.getType(), inputForValue.get());
+
+            if(!isInputTypeSimilarToOperation) {
+                return Either.right(componentsUtils.getResponseFormat(
+                        ActionStatus.INVALID_CONSUMPTION_TYPE, operationInputDefinition.getType()));
+            }
+            addGetInputValueToOperationInput(operation, operationInputDefinition, inputForValue.get());
+        }
+
+        return Either.left(operation);
+    }
+
+
+    private boolean isAssignedValueFromValidType(String operationInputType, Object actualValue) {
+        if (actualValue instanceof String) {
+            // validate static value
+            ToscaPropertyType actualType = ToscaPropertyType.isValidType(operationInputType);
+            PropertyTypeValidator validator = actualType.getValidator();
+            return validator.isValid((String)actualValue, operationInputType);
+        } else if (actualValue instanceof PropertyDefinition) {
+            // validate input / property value
+            String actualType = ((PropertyDefinition) actualValue).getType();
+            return actualType.equalsIgnoreCase(operationInputType);
+        } else if (actualValue instanceof OperationOutputDefinition) {
+            // validate input / output value
+            String actualType = ((OperationOutputDefinition) actualValue).getType();
+            return actualType.equalsIgnoreCase(operationInputType);
+        }
+        return false;
+    }
+
+    private void addGetInputValueToOperationInput(Operation operation,
+                                                  OperationInputDefinition operationInputDefinition,
+                                                  InputDefinition inputForValue) {
+        operation.getInputs().delete(operationInputDefinition);
+        Map<String, String> getInputMap = new HashMap<>();
+        getInputMap.put(ToscaFunctions.GET_INPUT.getFunctionName(), inputForValue.getName());
+        operationInputDefinition.setSourceProperty(inputForValue.getUniqueId());
+        operationInputDefinition.setToscaPresentationValue(JsonPresentationFields.GET_INPUT, getInputMap);
+        operationInputDefinition.setValue(new Gson().toJson(getInputMap));
+        operation.getInputs().add(operationInputDefinition);
+    }
+
     private Either<List<Map<String, Object>>, ActionStatus> getAuditRecordsForUncertifiedComponent(String componentUUID, String componentVersion) {
         // First Query
         Either<List<ResourceAdminEvent>, ActionStatus> eitherprevVerAudit = auditCassandraDao.getAuditByServiceIdAndPrevVersion(componentUUID, componentVersion);
index a60b0f0..c09fb91 100644 (file)
@@ -21,6 +21,7 @@ import static java.util.Collections.singletonMap;
 import static java.util.stream.Collectors.toList;
 import static org.apache.commons.collections.CollectionUtils.isEmpty;
 import static org.openecomp.sdc.be.dao.utils.MapUtil.toMap;
+import static org.openecomp.sdc.be.utils.PropertyDefinitionUtils.resolveGetInputProperties;
 
 @org.springframework.stereotype.Component
 public class ComponentInstanceInputsRedeclareHandler {
@@ -43,7 +44,8 @@ public class ComponentInstanceInputsRedeclareHandler {
         Map<String, List<PropertyDataDefinition>> allPropertiesForInstance = getAllGetPropertiesForInstance(container, newInstanceId);
         List<InputDefinition> previouslyDeclaredInputs = declaredInputsResolver.getPreviouslyDeclaredInputsToMerge(oldInputs, container, allPropertiesForInstance);
         inputsValuesMergingBusinessLogic.mergeComponentInputs(oldInputs, previouslyDeclaredInputs);
-        updateInputsAnnotations(allPropertiesForInstance.get(newInstanceId), newInstanceOriginType, previouslyDeclaredInputs);
+        Map<String, List<PropertyDataDefinition>> getInputProperties = resolveGetInputProperties(allPropertiesForInstance);
+        updateInputsAnnotations(getInputProperties.get(newInstanceId), newInstanceOriginType, previouslyDeclaredInputs);
 
         return updateInputs(container.getUniqueId(), previouslyDeclaredInputs);
     }
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceInterfacesMerge.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceInterfacesMerge.java
new file mode 100644 (file)
index 0000000..60e60b0
--- /dev/null
@@ -0,0 +1,72 @@
+package org.openecomp.sdc.be.components.merge.instance;
+
+import fj.data.Either;
+import java.util.List;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
+import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
+import org.openecomp.sdc.be.impl.ComponentsUtils;
+import org.openecomp.sdc.be.model.Component;
+import org.openecomp.sdc.be.model.ComponentInstance;
+import org.openecomp.sdc.be.model.ComponentInstanceInterface;
+import org.openecomp.sdc.be.model.User;
+import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade;
+import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
+import org.openecomp.sdc.exception.ResponseFormat;
+import org.springframework.beans.factory.annotation.Autowired;
+
+@org.springframework.stereotype.Component("ComponentInstanceInterfacesMerge")
+public class ComponentInstanceInterfacesMerge implements ComponentInstanceMergeInterface {
+
+    @Autowired
+    private ComponentsUtils componentsUtils;
+
+    @Autowired
+    private ToscaOperationFacade toscaOperationFacade;
+
+    @Override
+    public void saveDataBeforeMerge(DataForMergeHolder dataHolder, Component containerComponent, ComponentInstance currentResourceInstance, Component originComponent) {
+        dataHolder.setOrigInstanceNode(originComponent);
+        dataHolder.setOrigComponentInstanceInterfaces(containerComponent.safeGetComponentInstanceInterfaces(currentResourceInstance.getUniqueId()));
+    }
+
+    @Override
+    public Either<Component, ResponseFormat> mergeDataAfterCreate(User user, DataForMergeHolder dataHolder, Component updatedContainerComponent, String newInstanceId) {
+        List<ComponentInstanceInterface> origInstanceInterfaces = dataHolder.getOrigComponentInstanceInterfaces();
+        ActionStatus mergeStatus = mergeComponentInstanceInterfaces(updatedContainerComponent, newInstanceId, origInstanceInterfaces);
+        return Either.iif(!ActionStatus.OK.equals(mergeStatus), () -> componentsUtils.getResponseFormat(mergeStatus), () -> updatedContainerComponent);
+    }
+
+    private ActionStatus mergeComponentInstanceInterfaces(Component currentComponent, String instanceId, List<ComponentInstanceInterface> prevInstanceInterfaces) {
+        if (CollectionUtils.isEmpty(prevInstanceInterfaces) || MapUtils.isEmpty(currentComponent.getComponentInstancesInterfaces())) {
+            return ActionStatus.OK;
+        }
+
+        if(CollectionUtils.isEmpty(currentComponent.getComponentInstancesInterfaces().get(instanceId))){
+            return ActionStatus.OK;
+        }
+
+        currentComponent.getComponentInstancesInterfaces().get(instanceId).stream()
+            .forEach(newInterfaceDef -> newInterfaceDef.getOperationsMap().values()
+                .forEach(newOperationDef -> prevInstanceInterfaces.stream().filter(in -> in.getUniqueId().equals(newInterfaceDef.getUniqueId()))
+                    .forEach(prevInterfaceDef -> prevInterfaceDef.getOperationsMap().values().stream().filter(in1 -> in1.getUniqueId().equals(newOperationDef.getUniqueId()))
+                        .forEach(oldOperationDef -> mergeOperationInputDefinitions(oldOperationDef.getInputs(), newOperationDef.getInputs())))));
+
+        StorageOperationStatus updateStatus = toscaOperationFacade.updateComponentInstanceInterfaces(currentComponent, instanceId);
+        return componentsUtils.convertFromStorageResponse(updateStatus);
+    }
+
+
+    private void mergeOperationInputDefinitions(ListDataDefinition<OperationInputDefinition> origInputs, ListDataDefinition<OperationInputDefinition> newInputs){
+        newInputs.getListToscaDataDefinition()
+            .forEach(inp -> origInputs.getListToscaDataDefinition().stream().filter(in -> in.getInputId().equals(inp.getInputId()))
+                .forEach(in -> {
+                    inp.setSourceProperty(in.getSourceProperty());
+                    inp.setSource(in.getSource());
+                    inp.setValue(in.getValue());
+                }));
+    }
+
+}
index 81e2f4c..31b3207 100644 (file)
@@ -92,6 +92,7 @@ public class ComponentInstanceMergeDataBusinessLogic {
         filter.setIgnoreCapabiltyProperties(false);
         filter.setIgnoreArtifacts(false);
         filter.setIgnoreForwardingPath(false);
+        filter.setIgnoreComponentInstancesInterfaces(false);
         return toscaOperationFacade.getToscaElement(containerComponentId, filter);
     }
 }
index 7388819..b159cd5 100644 (file)
@@ -22,6 +22,7 @@ public class DataForMergeHolder {
     private Component origInstanceNode;
     private Component currInstanceNode;
     private String origComponentInstId;
+    private List<ComponentInstanceInterface> origComponentInstanceInterfaces;
 
     public DataForMergeHolder() {
         origComponentInstanceInputs = new ArrayList<>();
@@ -30,6 +31,7 @@ public class DataForMergeHolder {
         origCompInstDeploymentArtifactsCreatedOnTheInstance = new HashMap<>();
         origCompInstDeploymentArtifactsCreatedOnTheInstance = new HashMap<>();
         origInstanceCapabilities = new ArrayList<>();
+        origComponentInstanceInterfaces = new ArrayList<>();
     }
 
     List<ArtifactDefinition> getOrigComponentInstanceHeatEnvArtifacts() {
@@ -155,4 +157,12 @@ public class DataForMergeHolder {
     public void setOrigComponentInstId(String origComponentInstId) {
         this.origComponentInstId = origComponentInstId;
     }
+
+    public List<ComponentInstanceInterface> getOrigComponentInstanceInterfaces() {
+        return origComponentInstanceInterfaces;
+    }
+
+    public void setOrigComponentInstanceInterfaces(List<ComponentInstanceInterface> origComponentInstanceInterfaces) {
+        this.origComponentInstanceInterfaces = origComponentInstanceInterfaces;
+    }
 }
index 06e8db0..bd7a58c 100644 (file)
@@ -75,8 +75,6 @@ public abstract class DefaultPropertyDeclarator<PROPERTYOWNER extends Properties
 
     private InputDefinition declarePropertyInput(String componentId, PROPERTYOWNER propertiesOwner, List<PROPERTYTYPE> declaredProperties, ComponentInstancePropInput propInput) {
         PropertyDataDefinition prop = resolveProperty(declaredProperties, propInput);
-        propInput.setOwnerId(null);
-        propInput.setParentUniqueId(null);
         InputDefinition inputDefinition = createInput(componentId, propertiesOwner, propInput, prop);
         PROPERTYTYPE declaredProperty = createDeclaredProperty(prop);
         if(!declaredProperties.contains(declaredProperty)){
@@ -86,15 +84,19 @@ public abstract class DefaultPropertyDeclarator<PROPERTYOWNER extends Properties
         return inputDefinition;
     }
 
-    private InputDefinition createInput(String componentId, PROPERTYOWNER propertiesOwner, ComponentInstancePropInput propInput, PropertyDataDefinition prop) {
-        String generatedInputName = generateInputName(propertiesOwner instanceof
-                        Service ? null : propertiesOwner.getNormalizedName(),
-            propInput);
+    private InputDefinition createInput(String componentId, PROPERTYOWNER propertiesOwner,
+                                        ComponentInstancePropInput propInput, PropertyDataDefinition prop) {
+        String generatedInputPrefix = propertiesOwner.getNormalizedName();
+        if (propertiesOwner.getUniqueId().equals(propInput.getParentUniqueId())) {
+            //Creating input from property create on self using add property..Do not add the prefix
+            generatedInputPrefix = null;
+        }
+        String generatedInputName = generateInputName(generatedInputPrefix, propInput);
         return createInputFromProperty(componentId, propertiesOwner, generatedInputName, propInput, prop);
     }
 
     private String generateInputName(String inputName, ComponentInstancePropInput propInput) {
-        String declaredInputName = inputName;
+        String declaredInputName;
         String[] parsedPropNames = propInput.getParsedPropNames();
 
         if(parsedPropNames != null){
@@ -154,7 +156,6 @@ public abstract class DefaultPropertyDeclarator<PROPERTYOWNER extends Properties
         input.setInputPath(propertiesName);
         input.setInstanceUniqueId(propertiesOwner.getUniqueId());
         input.setPropertyId(propInput.getUniqueId());
-        input.setValue(null);
         changePropertyValueToGetInputValue(inputName, parsedPropNames, input, prop, complexProperty);
 
         if(prop instanceof IComponentInstanceConnectedElement) {
index 6615e9e..2727a8b 100644 (file)
 
 package org.openecomp.sdc.be.components.utils;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Optional;
 
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.MapUtils;
+import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
+import org.openecomp.sdc.be.datatypes.elements.OperationOutputDefinition;
 import org.openecomp.sdc.be.model.Component;
 import org.openecomp.sdc.be.model.InputDefinition;
 import org.openecomp.sdc.be.model.InterfaceDefinition;
 import org.openecomp.sdc.be.model.Operation;
+import org.openecomp.sdc.be.model.tosca.ToscaFunctions;
+import org.openecomp.sdc.be.tosca.utils.InterfacesOperationsToscaUtil;
 
 public class InterfaceOperationUtils {
 
@@ -66,7 +76,17 @@ public class InterfaceOperationUtils {
                        .filter(entry -> entry.getValue().getUniqueId().equals(operationId)).findAny();
     }
 
-    public static boolean isOperationInputMappedToComponentProperty(OperationInputDefinition input,
+    public static Optional<InterfaceDefinition> getInterfaceDefinitionFromOperationId(List<InterfaceDefinition> interfaces,
+            String operationId) {
+        if (CollectionUtils.isEmpty(interfaces)) {
+            return Optional.empty();
+        }
+        return interfaces.stream()
+                       .filter(interfaceDefinition -> interfaceDefinition.getOperationsMap().containsKey(operationId))
+                       .findAny();
+    }
+
+    public static boolean isOperationInputMappedToComponentInput(OperationInputDefinition input,
                                                                  List<InputDefinition> inputs) {
         if (CollectionUtils.isEmpty(inputs)) {
             return false;
@@ -77,5 +97,87 @@ public class InterfaceOperationUtils {
                 input.getInputId().substring(0, input.getInputId().lastIndexOf('.'))))) ;
     }
 
+    public static boolean isOperationInputMappedToOtherOperationOutput(String outputName,
+                                                                       List<OperationOutputDefinition>
+                                                                               otherOperationOutputs) {
+        if (CollectionUtils.isEmpty(otherOperationOutputs)) {
+            return false;
+        }
+        return otherOperationOutputs.stream()
+                .anyMatch(output -> output.getName().equals(outputName));
+
+    }
 
+    public static Map<String, List<String>> createMappedInputPropertyDefaultValue(String propertyName) {
+        Map<String, List<String>> getPropertyMap = new HashMap<>();
+        List<String> values = new ArrayList<>();
+        values.add(InterfacesOperationsToscaUtil.SELF);
+        if (Objects.nonNull(propertyName) && !propertyName.isEmpty()) {
+            values.addAll(Arrays.asList(propertyName.split("\\.")));
+        }
+        getPropertyMap.put(ToscaFunctions.GET_PROPERTY.getFunctionName(), values);
+        return getPropertyMap;
+    }
+
+    /**
+     * Get the list of outputs of other operations of all the interfaces in the component.
+     * @param currentOperationIdentifier Fully qualified operation name e.g. org.test.interfaces.node.lifecycle.Abc.stop
+     * @param componentInterfaces VF or service interfaces
+     */
+
+    public static ListDataDefinition<OperationOutputDefinition> getOtherOperationOutputsOfComponent(
+            String currentOperationIdentifier, Map<String, ? extends InterfaceDataDefinition> componentInterfaces) {
+        ListDataDefinition<OperationOutputDefinition> componentOutputs = new ListDataDefinition<>();
+        if (MapUtils.isEmpty(componentInterfaces)) {
+            return componentOutputs;
+        }
+        for (Map.Entry<String, ? extends InterfaceDataDefinition> interfaceDefinitionEntry :
+                componentInterfaces.entrySet()) {
+            String interfaceName = interfaceDefinitionEntry.getKey();
+            final Map<String, OperationDataDefinition> operations = interfaceDefinitionEntry.getValue().getOperations();
+            if (MapUtils.isEmpty(operations)) {
+                continue;
+            }
+            for (Map.Entry<String, OperationDataDefinition> operationEntry : operations.entrySet()) {
+                ListDataDefinition<OperationOutputDefinition> outputs = operationEntry.getValue().getOutputs();
+                String expectedOperationIdentifier = interfaceName + "." + operationEntry.getKey();
+                if (!currentOperationIdentifier.equals(expectedOperationIdentifier) && !outputs.isEmpty()) {
+                    outputs.getListToscaDataDefinition().forEach(componentOutputs::add);
+                }
+            }
+        }
+        return componentOutputs;
+    }
+
+    /**
+     * Create the value for operation input mapped to an operation output.
+     * @param propertyName the mapped other operation output full name
+     * @return input map for tosca
+     */
+    public static Map<String, List<String>> createMappedOutputDefaultValue(String componentName, String propertyName) {
+        Map<String, List<String>> getOperationOutputMap = new HashMap<>();
+        //For operation input mapped to other operation output parameter, the mapped property value
+        // should be of the format <interface name>.<operation name>.<output parameter name>
+        // Operation name and output param name should not contain "."
+        List<String> defaultMappedOperationOutputValue = new ArrayList<>();
+        String[] tokens = propertyName.split("\\.");
+        if (tokens.length > 2) {
+            defaultMappedOperationOutputValue.add(componentName);
+            String outputPropertyName = tokens[tokens.length - 1];
+            String operationName = tokens[tokens.length - 2];
+            String mappedPropertyInterfaceType =
+                    propertyName.substring(0, propertyName.indexOf(operationName + '.' + outputPropertyName) - 1);
+            defaultMappedOperationOutputValue.addAll(Arrays.asList(mappedPropertyInterfaceType, operationName,
+                    outputPropertyName));
+            getOperationOutputMap.put(ToscaFunctions.GET_OPERATION_OUTPUT.getFunctionName(),
+                    defaultMappedOperationOutputValue);
+        }
+        return getOperationOutputMap;
+    }
+
+    public static String getOperationOutputName(String fullOutputIdentifier) {
+        return fullOutputIdentifier.contains(".")
+                ? fullOutputIdentifier.substring(fullOutputIdentifier.lastIndexOf('.') + 1)
+                : fullOutputIdentifier;
+    }
 }
index 250fc03..f84c9a4 100644 (file)
 
 package org.openecomp.sdc.be.components.validation;
 
-import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.isOperationInputMappedToComponentProperty;
+import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.getOperationOutputName;
+import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.getOtherOperationOutputsOfComponent;
+import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.isOperationInputMappedToComponentInput;
 
 import com.google.common.collect.Sets;
-import fj.data.Either;
+
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -32,10 +34,13 @@ import java.util.Set;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
+
+import fj.data.Either;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.StringUtils;
 import org.openecomp.sdc.be.components.impl.ResponseFormatManager;
+import org.openecomp.sdc.be.components.utils.InterfaceOperationUtils;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
@@ -90,16 +95,49 @@ public class InterfaceOperationValidation {
         return Either.left(Boolean.TRUE);
     }
 
+    public Either<Boolean, ResponseFormat> validateDeleteOperationContainsNoMappedOutput(
+            Operation interfaceOperationToDelete, org.openecomp.sdc.be.model.Component component,
+            InterfaceDefinition storedInterfaceDefinition) {
+        ResponseFormatManager responseFormatManager = getResponseFormatManager();
+        List<OperationOutputDefinition> existingOperationOutputs =
+                getInterfaceOperationOutputs(interfaceOperationToDelete.getUniqueId(), component.getInterfaces());
+        if (existingOperationOutputs.isEmpty()) {
+            return Either.left(Boolean.TRUE);
+        }
+        String mappedOutputPrefix = storedInterfaceDefinition.getType() + "." + interfaceOperationToDelete.getName();
+        List<OperationInputDefinition> interfaceOperationInputs =
+                getOtherOperationInputsOfComponent(mappedOutputPrefix, component.getInterfaces());
+        Set<String> mappedOutputsInDeletedOperation = new HashSet<>();
+        Set<String> existingOperationOutputNames = existingOperationOutputs.stream()
+                .map(OperationOutputDefinition::getName)
+                .collect(Collectors.toSet());
+        for (String existingOperationOutputName : existingOperationOutputNames) {
+            Set<String> matchedOutputsMappedToInputs = interfaceOperationInputs.stream()
+                    .filter(operationInputDefinition -> operationInputDefinition.getInputId()
+                            .equals(mappedOutputPrefix + "." + existingOperationOutputName))
+                    .map(operationInputDefinition -> getOperationOutputName(operationInputDefinition.getInputId()))
+                    .collect(Collectors.toSet());
+            mappedOutputsInDeletedOperation.addAll(matchedOutputsMappedToInputs);
+        }
+
+        if (CollectionUtils.isNotEmpty(mappedOutputsInDeletedOperation)) {
+            return getMappedOutputErrorResponse(responseFormatManager, mappedOutputsInDeletedOperation,
+                    "Cannot delete interface operation with output(s) '{}' mapped to another operation input",
+                    ActionStatus.INTERFACE_OPERATION_DELETE_WITH_MAPPED_OUTPUT);
+        }
+        return Either.left(Boolean.TRUE);
+    }
+
     private Either<Boolean, ResponseFormat> validateAllowedOperationCountOnLocalInterfaceType(
             InterfaceDefinition inputInterfaceDefinition, InterfaceDefinition storedInterfaceDefinition,
             Map<String, InterfaceDefinition> globalInterfaceTypes, boolean isUpdate) {
 
         boolean isInterfaceTypeExistInGlobalType =
                 globalInterfaceTypes.values().stream().map(InterfaceDefinition::getType)
-                .anyMatch(type -> type.equalsIgnoreCase(inputInterfaceDefinition.getType()));
-        if (!isInterfaceTypeExistInGlobalType && (inputInterfaceDefinition.getOperations().size() > 1
-                || (!isUpdate && storedInterfaceDefinition != null
-                && storedInterfaceDefinition.getType().equalsIgnoreCase(inputInterfaceDefinition.getType())))) {
+                        .anyMatch(type -> type.equalsIgnoreCase(inputInterfaceDefinition.getType()));
+        if (!isInterfaceTypeExistInGlobalType
+                && isValidOperationOnLocalInterfaceType(inputInterfaceDefinition, storedInterfaceDefinition,
+                isUpdate)) {
             return Either.right(getResponseFormatManager()
                     .getResponseFormat(ActionStatus.INTERFACE_OPERATION_INVALID_FOR_LOCAL_TYPE,
                             inputInterfaceDefinition.getType()));
@@ -108,22 +146,32 @@ public class InterfaceOperationValidation {
         return Either.left(Boolean.TRUE);
     }
 
+    private boolean isValidOperationOnLocalInterfaceType(InterfaceDefinition inputInterfaceDefinition,
+                                                         InterfaceDefinition storedInterfaceDefinition,
+                                                         boolean isUpdate) {
+        return inputInterfaceDefinition.getOperations().size() > 1
+                || (!isUpdate && storedInterfaceDefinition != null
+                && storedInterfaceDefinition.getType()
+                .equalsIgnoreCase(inputInterfaceDefinition.getType()));
+    }
+
     private Either<Boolean, ResponseFormat> validateAllowedOperationsOnGlobalInterfaceType(
             InterfaceDefinition interfaceDefinition, Map<String, InterfaceDefinition> globalInterfaceTypes) {
 
-        if (globalInterfaceTypes != null) {
-            boolean isOperationValidOnGlobalInterfaceType = Stream.of(interfaceDefinition)
-                    .filter(interfaceDef -> globalInterfaceTypes.values().stream().anyMatch(interfaceDef1 ->
-                            interfaceDef1.getType().equalsIgnoreCase(interfaceDef.getType())))
-                    .flatMap(interfaceDef -> interfaceDef.getOperationsMap().values().stream().map(Operation::getName))
-                    .allMatch(operationName -> globalInterfaceTypes.values().stream()
-                            .flatMap(interfaceDef -> interfaceDef.getOperationsMap().keySet().stream())
-                            .anyMatch(opName -> opName.equalsIgnoreCase(operationName)));
-            if (!isOperationValidOnGlobalInterfaceType) {
-                return Either.right(getResponseFormatManager()
-                        .getResponseFormat(ActionStatus.INTERFACE_OPERATION_INVALID_FOR_GLOBAL_TYPE,
-                                interfaceDefinition.getType()));
-            }
+        if (globalInterfaceTypes == null) {
+            return Either.left(Boolean.TRUE);
+        }
+        boolean isOperationValidOnGlobalInterfaceType = Stream.of(interfaceDefinition)
+                .filter(interfaceDef -> globalInterfaceTypes.values().stream().anyMatch(interfaceDef1 ->
+                        interfaceDef1.getType().equalsIgnoreCase(interfaceDef.getType())))
+                .flatMap(interfaceDef -> interfaceDef.getOperationsMap().values().stream().map(Operation::getName))
+                .allMatch(operationName -> globalInterfaceTypes.values().stream()
+                        .flatMap(interfaceDef -> interfaceDef.getOperationsMap().keySet().stream())
+                        .anyMatch(opName -> opName.equalsIgnoreCase(operationName)));
+        if (!isOperationValidOnGlobalInterfaceType) {
+            return Either.right(getResponseFormatManager()
+                    .getResponseFormat(ActionStatus.INTERFACE_OPERATION_INVALID_FOR_GLOBAL_TYPE,
+                            interfaceDefinition.getType()));
         }
         return Either.left(Boolean.TRUE);
     }
@@ -212,33 +260,47 @@ public class InterfaceOperationValidation {
                     .collect(Collectors.toSet());
         }
         String mappedOutputPrefix = interfaceDefinition.getType() + "." + interfaceOperation.getName();
+        //Get the deleted outputs (name changed also equivalent to deleted)
         Set<String> deletedOutputs = Sets.difference(existingOperationOutputNames, currentOperationOutputNames);
-        Set<String> deletedMappedOutputs = deletedOutputs.stream()
-                .filter(deletedOutputName -> isMappedOutputDeleted(mappedOutputPrefix, deletedOutputName,
-                        component.getInterfaces()))
-                .map(this::getOperationOutputName)
-                .collect(Collectors.toSet());
+        Set<String> deletedMappedOutputs = getModifiedMappedOutputs(deletedOutputs, mappedOutputPrefix,
+                component.getInterfaces());
 
         if (CollectionUtils.isNotEmpty(deletedMappedOutputs)) {
-            return getMappedOutputErrorResponse(responseFormatManager, deletedMappedOutputs);
+            return getMappedOutputErrorResponse(responseFormatManager, deletedMappedOutputs,
+                    "Cannot update or delete interface operation output(s) '{}' mapped to an operation input",
+                    ActionStatus.INTERFACE_OPERATION_MAPPED_OUTPUT_MODIFIED);
         }
 
         if (currentOutputs != null && !currentOutputs.isEmpty()) {
+            //Get the unchanged outputs based on name to see if other attributes (type/mandatory) have not been changed
             Set<String> unchangedOutputNames = Sets.intersection(existingOperationOutputNames,
                     currentOperationOutputNames);
-            Set<String> modifiedMappedOutputNames =
-                    getModifiedMappedOutputNames(currentOutputs.getListToscaDataDefinition(),
+            Set<String> modifiedOutputNames =
+                    getModifiedOutputNames(currentOutputs.getListToscaDataDefinition(),
                             existingOperationOutputs, unchangedOutputNames);
+            Set<String> modifiedMappedOutputNames = getModifiedMappedOutputs(modifiedOutputNames, mappedOutputPrefix,
+                    component.getInterfaces());
             if (CollectionUtils.isNotEmpty(modifiedMappedOutputNames)) {
-                return getMappedOutputErrorResponse(responseFormatManager, modifiedMappedOutputNames);
+                return getMappedOutputErrorResponse(responseFormatManager, modifiedMappedOutputNames,
+                        "Cannot update or delete interface operation output(s) '{}' mapped to an operation input",
+                        ActionStatus.INTERFACE_OPERATION_MAPPED_OUTPUT_MODIFIED);
             }
         }
 
         return Either.left(Boolean.TRUE);
     }
 
-    private boolean isMappedOutputDeleted(String mappedOutputPrefix, String outputName,
-                                          Map<String, InterfaceDefinition> componentInterfaces) {
+    private Set<String> getModifiedMappedOutputs(Set<String> modifiedOutputNames, String mappedOutputPrefix,
+                                                 Map<String, InterfaceDefinition> componentInterfaces) {
+        return modifiedOutputNames.stream()
+                .filter(modifiedOutputName -> isMappedOutputModified(mappedOutputPrefix, modifiedOutputName,
+                        componentInterfaces))
+                .map(InterfaceOperationUtils::getOperationOutputName)
+                .collect(Collectors.toSet());
+    }
+
+    private boolean isMappedOutputModified(String mappedOutputPrefix, String outputName,
+                                           Map<String, InterfaceDefinition> componentInterfaces) {
         List<OperationInputDefinition> interfaceOperationInputs =
                 getOtherOperationInputsOfComponent(mappedOutputPrefix, componentInterfaces);
         return interfaceOperationInputs.stream()
@@ -246,16 +308,16 @@ public class InterfaceOperationValidation {
                         .equals(mappedOutputPrefix + "." + outputName));
     }
 
-    private static Set<String> getModifiedMappedOutputNames(List<OperationOutputDefinition> currentOperationOutputs,
-            List<OperationOutputDefinition> existingOperationOutputs,
-            Set<String> unchangedOutputNames) {
+    private static Set<String> getModifiedOutputNames(List<OperationOutputDefinition> currentOperationOutputs,
+                                                      List<OperationOutputDefinition> existingOperationOutputs,
+                                                      Set<String> unchangedOutputNames) {
         Set<String> modifiedOutputDefinitionNames = new HashSet<>();
-        Map<String, OperationOutputDefinition> newOutputMap =
-                currentOperationOutputs.stream().collect(Collectors.toMap(OperationOutputDefinition::getName,
+        Map<String, OperationOutputDefinition> newOutputMap = currentOperationOutputs.stream()
+                .collect(Collectors.toMap(OperationOutputDefinition::getName,
                         (OperationOutputDefinition operationOutputDefinition) -> operationOutputDefinition));
 
-        Map<String, OperationOutputDefinition> existingOutputMap =
-                existingOperationOutputs.stream().collect(Collectors.toMap(OperationOutputDefinition::getName,
+        Map<String, OperationOutputDefinition> existingOutputMap = existingOperationOutputs.stream()
+                .collect(Collectors.toMap(OperationOutputDefinition::getName,
                         (OperationOutputDefinition operationOutputDefinition) -> operationOutputDefinition));
 
         for (String outputName : unchangedOutputNames) {
@@ -270,12 +332,12 @@ public class InterfaceOperationValidation {
     }
 
     private Either<Boolean, ResponseFormat> getMappedOutputErrorResponse(ResponseFormatManager responseFormatManager,
-                                                                         Set<String> modifiedMappedOutputs) {
+                                                                         Set<String> modifiedMappedOutputs,
+                                                                         String message,
+                                                                         ActionStatus errorStatus) {
         String modifiedOutputNameList = String.join(",", modifiedMappedOutputs);
-        LOGGER.error("Cannot update or delete interface operation output(s) '{}' mapped to an operation input",
-                modifiedOutputNameList);
-        ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus
-                .INTERFACE_OPERATION_MAPPED_OUTPUT_MODIFIED, modifiedOutputNameList);
+        LOGGER.error(message, modifiedOutputNameList);
+        ResponseFormat errorResponse = responseFormatManager.getResponseFormat(errorStatus, modifiedOutputNameList);
         return Either.right(errorResponse);
     }
 
@@ -461,11 +523,11 @@ public class InterfaceOperationValidation {
         List<OperationInputDefinition> inputListToscaDataDefinition =
                 operation.getInputs().getListToscaDataDefinition();
         for (OperationInputDefinition inputDefinition : inputListToscaDataDefinition) {
-            if (isOperationInputMappedToComponentProperty(inputDefinition, component.getInputs())) {
+            if (isOperationInputMappedToComponentInput(inputDefinition, component.getInputs())) {
                 isOperationInputToInputPropertyMappingValid = true;
             } else {
                 mappingName = inputDefinition.getInputId().contains(".")
-                        ? inputDefinition.getInputId().substring(inputDefinition.getInputId().lastIndexOf(".") + 1)
+                        ? inputDefinition.getInputId().substring(inputDefinition.getInputId().lastIndexOf('.') + 1)
                         : inputDefinition.getInputId();
                 break;
             }
@@ -476,8 +538,9 @@ public class InterfaceOperationValidation {
 
         //Mapped property not found in the component properties.. Check in other operation output parameters of
         // component (other operation => not having the same full name)
+        String actualOperationIdentifier = inputInterfaceDefinition.getType() + "." + operation.getName();
         ListDataDefinition<OperationOutputDefinition> outputListDataDefinition =
-                getOtherOperationOutputsOfComponent(inputInterfaceDefinition.getType(), operation.getName(), component);
+                getOtherOperationOutputsOfComponent(actualOperationIdentifier, component.getInterfaces());
 
         List<OperationOutputDefinition> componentOutputsFromOtherOperations =
                 outputListDataDefinition.getListToscaDataDefinition();
@@ -505,38 +568,6 @@ public class InterfaceOperationValidation {
                 .anyMatch(output -> output.getName().equals(mappedOutputName));
     }
 
-    /**
-     * Get the list of outputs of other operations of all the interfaces in the component.
-     * @param currentInterfaceName Fully qualified interface name e.g. org.test.interfaces.node.lifecycle.Abc
-     * @param currentOperationName Name entered on the operation screen e.g. create
-     * @param component VF or service
-     */
-
-    private ListDataDefinition<OperationOutputDefinition> getOtherOperationOutputsOfComponent(
-            String currentInterfaceName, String currentOperationName, org.openecomp.sdc.be.model.Component component) {
-        ListDataDefinition<OperationOutputDefinition> componentOutputs = new ListDataDefinition<>();
-        Map<String, InterfaceDefinition> componentInterfaces = component.getInterfaces();
-        if (MapUtils.isEmpty(componentInterfaces)) {
-            return componentOutputs;
-        }
-        for (Map.Entry<String, InterfaceDefinition> interfaceDefinitionEntry : componentInterfaces.entrySet()) {
-            String interfaceName = interfaceDefinitionEntry.getKey();
-            final Map<String, OperationDataDefinition> operations = interfaceDefinitionEntry.getValue().getOperations();
-            if (MapUtils.isEmpty(operations)) {
-                continue;
-            }
-            String actualOperationIdentifier = currentInterfaceName + "." + currentOperationName;
-            for (Map.Entry<String, OperationDataDefinition> operationEntry : operations.entrySet()) {
-                ListDataDefinition<OperationOutputDefinition> outputs = operationEntry.getValue().getOutputs();
-                String expectedOperationIdentifier = interfaceName + "." + operationEntry.getKey();
-                if (!actualOperationIdentifier.equals(expectedOperationIdentifier) && !outputs.isEmpty()) {
-                    outputs.getListToscaDataDefinition().forEach(componentOutputs::add);
-                }
-            }
-        }
-        return componentOutputs;
-    }
-
     /**
      * Get the input definitions of other operations of the component from current as well as other interfaces.
      * @param currentOperationIdentifier Identifier for the request operation (interface_name.operation_name)
@@ -566,12 +597,6 @@ public class InterfaceOperationValidation {
         return otherOperationInputs;
     }
 
-    private String getOperationOutputName(String outputName) {
-        return outputName.contains(".")
-                ? outputName.substring(outputName.lastIndexOf(".") + 1)
-                : outputName;
-    }
-
     /**
      * Get the output of an operation in an interface.
      * @param inputOperationId Unique identifier for the request operation
index b76664f..0dddfe5 100644 (file)
 
 package org.openecomp.sdc.be.datamodel.utils;
 
+import static java.util.stream.Collectors.groupingBy;
+import static java.util.stream.Collectors.toList;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 import org.openecomp.sdc.be.components.impl.GroupTypeBusinessLogic;
 import org.openecomp.sdc.be.components.impl.PolicyTypeBusinessLogic;
 import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
@@ -27,16 +37,21 @@ import org.openecomp.sdc.be.datatypes.components.ServiceMetadataDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition;
 import org.openecomp.sdc.be.datatypes.enums.ComponentFieldsEnum;
 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
-import org.openecomp.sdc.be.model.*;
+import org.openecomp.sdc.be.model.CapabilityDefinition;
+import org.openecomp.sdc.be.model.Component;
+import org.openecomp.sdc.be.model.GroupDefinition;
+import org.openecomp.sdc.be.model.PolicyDefinition;
+import org.openecomp.sdc.be.model.Resource;
+import org.openecomp.sdc.be.model.Service;
 import org.openecomp.sdc.be.tosca.utils.NodeFilterConverter;
-import org.openecomp.sdc.be.ui.model.*;
+import org.openecomp.sdc.be.ui.model.UiComponentDataTransfer;
+import org.openecomp.sdc.be.ui.model.UiComponentMetadata;
+import org.openecomp.sdc.be.ui.model.UiResourceDataTransfer;
+import org.openecomp.sdc.be.ui.model.UiResourceMetadata;
+import org.openecomp.sdc.be.ui.model.UiServiceDataTransfer;
+import org.openecomp.sdc.be.ui.model.UiServiceMetadata;
 import org.openecomp.sdc.common.log.wrappers.Logger;
 
-import java.util.*;
-
-import static java.util.stream.Collectors.groupingBy;
-import static java.util.stream.Collectors.toList;
-
 @org.springframework.stereotype.Component("uiComponentDataConverter")
 public class UiComponentDataConverter {
 
@@ -109,6 +124,16 @@ public class UiComponentDataConverter {
                     NodeFilterConverter nodeFilterConverter = new NodeFilterConverter();
                     dataTransfer.setNodeFilterData(nodeFilterConverter.convertDataMapToUI(component.getNodeFilterComponents()));
                 }
+                break;
+            case COMPONENT_INSTANCES_INTERFACES:
+                setComponentInstanceInterfaces(dataTransfer, component);
+                break;
+            case PROPERTIES:
+                setProperties(dataTransfer, component);
+                break;
+            case INTERFACES:
+                setInterfaces(dataTransfer, component);
+                break;
             default:
                 break;
         }
@@ -137,7 +162,6 @@ public class UiComponentDataConverter {
             dataTransfer.setComponentInstancesInputs(component.getComponentInstancesInputs());
         }
     }
-
     private void setComponentInstanceAttributes(UiComponentDataTransfer dataTransfer, Component component) {
         if (component.getComponentInstancesAttributes() == null) {
             dataTransfer.setComponentInstancesAttributes(new HashMap<>());
@@ -145,7 +169,6 @@ public class UiComponentDataConverter {
             dataTransfer.setComponentInstancesAttributes(component.getComponentInstancesAttributes());
         }
     }
-
     private void setArtifacts(UiComponentDataTransfer dataTransfer, Component component) {
         if (component.getArtifacts() == null) {
             dataTransfer.setArtifacts(new HashMap<>());
@@ -153,7 +176,6 @@ public class UiComponentDataConverter {
             dataTransfer.setArtifacts(component.getArtifacts());
         }
     }
-
     private void setToscaArtifacts(UiComponentDataTransfer dataTransfer, Component component) {
         if (component.getToscaArtifacts() == null) {
             dataTransfer.setToscaArtifacts(new HashMap<>());
@@ -221,6 +243,30 @@ public class UiComponentDataConverter {
         }
     }
 
+    private void setProperties(UiComponentDataTransfer dataTransfer, Component component) {
+        if (component.getProperties() == null) {
+            dataTransfer.setProperties(new ArrayList<>());
+        } else {
+            dataTransfer.setProperties(component.getProperties());
+        }
+    }
+
+    private void setInterfaces(UiComponentDataTransfer dataTransfer, Component component) {
+        if (component.getInterfaces() == null) {
+            dataTransfer.setInterfaces(new HashMap<>());
+        } else {
+            dataTransfer.setInterfaces(component.getInterfaces());
+        }
+    }
+
+    private void setComponentInstanceInterfaces(UiComponentDataTransfer dataTransfer, Component component) {
+        if (component.getComponentInstancesInterfaces() == null) {
+            dataTransfer.setComponentInstancesInterfaces(new HashMap<>());
+        } else {
+            dataTransfer.setComponentInstancesInterfaces(component.getComponentInstancesInterfaces());
+        }
+    }
+
     private void setNonExcludedGroups(UiComponentDataTransfer dataTransfer, Component component) {
         List<GroupDefinition> groups = component.getGroups();
         if (groups == null) {
@@ -254,15 +300,6 @@ public class UiComponentDataConverter {
                 continue;
             }
             switch (field) {
-
-                case PROPERTIES:
-                    setProperties(resource, dataTransfer);
-                    break;
-
-                case INTERFACES:
-                    setInterfaces(resource, dataTransfer);
-                    break;
-
                 case DERIVED_FROM:
                     setDerivedFrom(resource, dataTransfer);
                     break;
@@ -287,22 +324,6 @@ public class UiComponentDataConverter {
         return dataTransfer;
     }
 
-    private void setProperties(Resource resource, UiResourceDataTransfer dataTransfer) {
-        if (resource.getProperties() == null) {
-            dataTransfer.setProperties(new ArrayList<>());
-        } else {
-            dataTransfer.setProperties(resource.getProperties());
-        }
-    }
-
-    private void setInterfaces(Resource resource, UiResourceDataTransfer dataTransfer) {
-        if (resource.getInterfaces() == null) {
-            dataTransfer.setInterfaces(new HashMap<>());
-        } else {
-            dataTransfer.setInterfaces(resource.getInterfaces());
-        }
-    }
-
     private void setDerivedFrom(Resource resource, UiResourceDataTransfer dataTransfer) {
         if (resource.getDerivedFrom() == null) {
             dataTransfer.setDerivedFrom(new ArrayList<>());
@@ -338,7 +359,6 @@ public class UiComponentDataConverter {
             switch (field) {
                 case SERVICE_API_ARTIFACTS:
                     setServiceApiArtifacts(service, dataTransfer);
-
                     break;
                 case FORWARDING_PATHS:
                     setForwardingPaths(service, dataTransfer);
@@ -347,9 +367,6 @@ public class UiComponentDataConverter {
                     UiServiceMetadata metadata = new UiServiceMetadata(service.getCategories(), (ServiceMetadataDataDefinition) service.getComponentMetadataDefinition().getMetadataDataDefinition());
                     dataTransfer.setMetadata(metadata);
                     break;
-                case INTERFACES:
-                    setInterfaces(service, dataTransfer);
-                    break;
                 default:
                     setUiTranferDataByFieldName(dataTransfer, service, fieldName);
             }
@@ -373,14 +390,6 @@ public class UiComponentDataConverter {
         }
     }
 
-    private void setInterfaces(Service service, UiServiceDataTransfer dataTransfer) {
-        if (service.getInterfaces() == null) {
-            dataTransfer.setInterfaces(new HashMap<>());
-        } else {
-            dataTransfer.setInterfaces(service.getInterfaces());
-        }
-    }
-
     public static UiComponentMetadata convertToUiComponentMetadata(Component component) {
 
         UiComponentMetadata uiComponentMetadata = null;
index 0930daa..9f6fb9f 100644 (file)
@@ -756,6 +756,9 @@ public class ComponentsUtils {
         case COMPONENT_IS_ARCHIVED:
             responseEnum = ActionStatus.COMPONENT_IS_ARCHIVED;
             break;
+        case DECLARED_INPUT_USED_BY_OPERATION:
+            responseEnum = ActionStatus.DECLARED_INPUT_USED_BY_OPERATION;
+            break;
        default:
             responseEnum = ActionStatus.GENERAL_ERROR;
             break;
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceConsumptionServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceConsumptionServlet.java
new file mode 100644 (file)
index 0000000..4ed2f95
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * 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.
+ */
+
+package org.openecomp.sdc.be.servlets;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonParseException;
+import com.jcabi.aspects.Loggable;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import fj.data.Either;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import org.apache.commons.lang3.StringUtils;
+import org.json.simple.JSONArray;
+import org.json.simple.parser.JSONParser;
+import org.json.simple.parser.ParseException;
+import org.openecomp.sdc.be.components.impl.InterfaceOperationBusinessLogic;
+import org.openecomp.sdc.be.components.impl.ServiceBusinessLogic;
+import org.openecomp.sdc.be.config.BeEcompErrorManager;
+import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
+import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
+import org.openecomp.sdc.be.model.Operation;
+import org.openecomp.sdc.be.model.User;
+import org.openecomp.sdc.be.model.tosca.ToscaFunctions;
+import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
+import org.openecomp.sdc.be.types.ServiceConsumptionData;
+import org.openecomp.sdc.be.types.ServiceConsumptionSource;
+import org.openecomp.sdc.common.api.Constants;
+import org.openecomp.sdc.exception.ResponseFormat;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.inject.Singleton;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+@Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
+@Path("/v1/catalog")
+@Api(value = "Service Consumption Servlet", description = "Service Consumption Servlet")
+@Singleton
+public class ServiceConsumptionServlet extends BeGenericServlet {
+
+  private static final Logger log = LoggerFactory.getLogger(ServiceConsumptionServlet.class);
+
+  @POST
+  @Path("/services/{serviceId}/consumption/{serviceInstanceId}")
+  @Consumes(MediaType.APPLICATION_JSON)
+  @Produces(MediaType.APPLICATION_JSON)
+  @ApiOperation(value = "Service consumption on operation", httpMethod = "POST",
+      notes = "Returns consumption data", response = Response.class)
+      @ApiResponses(value = { @ApiResponse(code = 201, message = "Service property created"),
+      @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
+      @ApiResponse(code = 409, message = "Service property already exist") })
+  public Response addInputToServiceOperation(@PathParam("serviceId")final String serviceId,
+                                             @PathParam("serviceInstanceId")final String serviceInstanceId,
+                                             @ApiParam(value = "Service Consumption Data", required = true) String data,
+                                             @Context final HttpServletRequest request,
+                                             @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+    ServletContext context = request.getSession().getServletContext();
+
+    String url = request.getMethod() + " " + request.getRequestURI();
+    log.debug("Start handle request of {} modifier id is {} data is {}", url, userId, data);
+    User modifier = new User();
+    modifier.setUserId(userId);
+
+    try {
+
+      Either<Map<String, List<ServiceConsumptionData>>, ResponseFormat> dataFromJson =
+          getServiceConsumptionData(data, modifier);
+      if(dataFromJson.isRight()) {
+        return buildErrorResponse(dataFromJson.right().value());
+      }
+
+      Map<String, List<ServiceConsumptionData>> serviceConsumptionDataMap = dataFromJson.left().value();
+      ServiceBusinessLogic serviceBL = getServiceBL(context);
+
+      for(Entry<String, List<ServiceConsumptionData>> consumptionEntry : serviceConsumptionDataMap.entrySet()) {
+        List<ServiceConsumptionData> consumptionList = consumptionEntry.getValue();
+        Either<List<Operation>, ResponseFormat> operationEither =
+            serviceBL.addServiceConsumptionData(serviceId, serviceInstanceId,
+                consumptionEntry.getKey(), consumptionList, userId);
+        if (operationEither.isRight()) {
+          return buildErrorResponse(operationEither.right().value());
+        }
+      }
+
+      return buildOkResponse(serviceConsumptionDataMap);
+
+    }
+    catch (Exception e) {
+      BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create Operation Inputs");
+      log.debug("Create Operation Inputs failed with exception", e);
+      ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR);
+      return buildErrorResponse(responseFormat);
+    }
+
+  }
+
+  @GET
+  @Path("/services/{serviceId}/consumption/{serviceInstanceId}/interfaces/{interfaceId}/operations/{operationId}/inputs")
+  @Consumes(MediaType.APPLICATION_JSON)
+  @Produces(MediaType.APPLICATION_JSON)
+  public Response getInputsListOfOperation(@PathParam("serviceId")final String serviceId,
+                                           @PathParam("serviceInstanceId")final String serviceInstanceId,
+                                           @PathParam("interfaceId")final String interfaceId,
+                                           @PathParam("operationId")final String operationId,
+                                           @Context final HttpServletRequest request,
+                                           @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+
+    ServletContext context = request.getSession().getServletContext();
+
+    String url = request.getMethod() + " " + request.getRequestURI();
+    log.debug("Start handle request of {} modifier id is {}", url, userId);
+    User user = new User();
+    user.setUserId(userId);
+
+    try {
+      InterfaceOperationBusinessLogic interfaceOperationBL = getInterfaceOperationBL(context);
+      Either<List<OperationInputDefinition>, ResponseFormat> inputsEither =
+          interfaceOperationBL.getInputsListForOperation(serviceId, serviceInstanceId, interfaceId, operationId, user);
+
+      if(inputsEither.isRight()) {
+        return buildErrorResponse(inputsEither.right().value());
+      }
+
+      List<OperationInputDefinition> inputs = inputsEither.left().value();
+      updateOperationInputListForUi(inputs);
+      return buildOkResponse(inputs);
+    }
+    catch (Exception e) {
+      BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Operation Inputs");
+      log.debug("Get Operation Inputs failed with exception", e);
+      ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR);
+      return buildErrorResponse(responseFormat);
+    }
+  }
+
+  private void updateOperationInputListForUi(List<OperationInputDefinition> inputsList) {
+    for(OperationInputDefinition input : inputsList) {
+
+      String value = input.getValue();
+      // No Additional UI mapping needed for STATIC source
+      if(StringUtils.isEmpty(value)
+              || ServiceConsumptionSource.STATIC.getSource().equals(input.getSource())) {
+        continue;
+      }
+
+
+      // Additional UI mapping needed for other sources
+      try {
+        Map<String, Object> valueAsMap = (new Gson()).fromJson(value, Map.class);
+        String toscaFunction = valueAsMap.keySet().iterator().next();
+        Object consumptionValueName = valueAsMap.values().iterator().next();
+        if(consumptionValueName instanceof List) {
+          List<Object> toscaFunctionList = (List<Object>) consumptionValueName;
+          String consumptionInputValue = null;
+          if (ToscaFunctions.GET_PROPERTY.getFunctionName().equals(toscaFunction)) {
+            consumptionInputValue = String.valueOf(toscaFunctionList.get(1));
+          } else if (ToscaFunctions.GET_OPERATION_OUTPUT.getFunctionName().equals(toscaFunction)) {
+            //Return full output name
+            consumptionInputValue =
+                    toscaFunctionList.get(1) + "." + toscaFunctionList.get(2) + "." +toscaFunctionList.get(3);
+          }
+          input.setValue(consumptionInputValue);
+        } else {
+          input.setValue(String.valueOf(consumptionValueName));
+        }
+      }
+      catch(JsonParseException ex){
+        log.info("This means it is static value for which no changes are needed");
+      }
+    }
+  }
+
+
+  private Either<Map<String, List<ServiceConsumptionData>>, ResponseFormat> getServiceConsumptionData(String data,
+                                                                                                      User user) {
+    JSONParser parser = new JSONParser();
+    Map<String, List<ServiceConsumptionData>> serviceConsumptionDataMap = new HashMap<>();
+
+    try {
+      JSONArray operationsArray = (JSONArray) parser.parse(data);
+      Iterator iterator = operationsArray.iterator();
+      while (iterator.hasNext()) {
+        Map next = (Map) iterator.next();
+        Entry consumptionEntry = (Entry) next.entrySet().iterator().next();
+        String operationId = (String) consumptionEntry.getKey();
+        Object value = consumptionEntry.getValue();
+
+        JSONArray inputsArray = (JSONArray) parser.parse(value.toString());
+        serviceConsumptionDataMap.putIfAbsent(operationId, new ArrayList<>());
+        for(Object consumptionObject : inputsArray) {
+          Either<ServiceConsumptionData, ResponseFormat> serviceDataEither =
+              getComponentsUtils()
+                  .convertJsonToObjectUsingObjectMapper(consumptionObject.toString(), user, ServiceConsumptionData
+                      .class, AuditingActionEnum.CREATE_RESOURCE, ComponentTypeEnum.SERVICE);
+          if(serviceDataEither.isRight()) {
+            return Either.right(serviceDataEither.right().value());
+          }
+
+          serviceConsumptionDataMap.get(operationId).add(serviceDataEither.left().value());
+        }
+      }
+    }
+    catch (ParseException e) {
+      log.info("Conetnt is invalid - {}", data);
+      return Either.right(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
+    }
+    return Either.left(serviceConsumptionDataMap);
+  }
+}
index da0ec1c..d3d4c2d 100644 (file)
@@ -45,6 +45,7 @@ import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade;
 import org.openecomp.sdc.be.model.jsontitan.utils.ModelConverter;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
+import org.openecomp.sdc.be.model.tosca.ToscaFunctions;
 import org.openecomp.sdc.be.model.tosca.converters.ToscaValueBaseConverter;
 import org.openecomp.sdc.be.tosca.model.*;
 import org.openecomp.sdc.be.tosca.utils.ForwardingPathToscaUtil;
@@ -509,27 +510,8 @@ public class ToscaExportHandler {
     }
 
     private Either<ToscaTemplate, ToscaError> convertNodeType(Map<String, Component> componentsCache, Component component, ToscaTemplate toscaNode,
-            Map<String, ToscaNodeType> nodeTypes) {
-        log.debug("start convert node type for {}", component.getUniqueId());
-        ToscaNodeType toscaNodeType = createNodeType(component);
-
-        Either<Map<String, DataTypeDefinition>, TitanOperationStatus> dataTypesEither = dataTypeCache.getAll();
-        if (dataTypesEither.isRight()) {
-            log.debug("Failed to fetch all data types :", dataTypesEither.right().value());
-            return Either.right(ToscaError.GENERAL_ERROR);
-        }
-
-        Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
-        Either<ToscaNodeType, ToscaError> properties = propertyConvertor.convertProperties(component, toscaNodeType,
-                dataTypes);
-        if (properties.isRight()) {
-            return Either.right(properties.right().value());
-        }
-        toscaNodeType = properties.left().value();
-        log.debug("Properties converted for {}", component.getUniqueId());
-
-        // Extracted to method for code reuse
-        return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes);
+                                                              Map<String, ToscaNodeType> nodeTypes) {
+        return convertInterfaceNodeType(componentsCache, component, toscaNode, nodeTypes, false);
     }
 
     private Either<ToscaTemplate, ToscaError> convertInterfaceNodeType(Map<String, Component> componentsCache,
@@ -546,10 +528,10 @@ public class ToscaExportHandler {
             return Either.right(ToscaError.GENERAL_ERROR);
         }
         List<String> allGlobalInterfaceTypes = lifecycleTypeEither.left().value()
-                                                                  .values()
-                                                                  .stream()
-                                                                  .map(interfaceDef -> interfaceDef.getType())
-                                                                  .collect(Collectors.toList());
+                .values()
+                .stream()
+                .map(InterfaceDataDefinition::getType)
+                .collect(Collectors.toList());
         toscaNode.setInterface_types(addInterfaceTypeElement(component, allGlobalInterfaceTypes));
 
         Either<Map<String, DataTypeDefinition>, TitanOperationStatus> dataTypesEither = dataTypeCache.getAll();
@@ -570,16 +552,40 @@ public class ToscaExportHandler {
         if(CollectionUtils.isNotEmpty(component.getProperties())) {
             List<PropertyDefinition> properties = component.getProperties();
             mergedProperties = properties.stream().collect(Collectors.toMap(
-                PropertyDataDefinition::getName,
-                property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY)));
+                    PropertyDataDefinition::getName,
+                    property -> propertyConvertor.convertProperty(dataTypes, property,
+                            PropertyConvertor.PropertyType.PROPERTY)));
         }
-        if (!mergedProperties.isEmpty()) {
+        if (MapUtils.isNotEmpty(mergedProperties) && Objects.nonNull(inputDef)) {
+            resolveDefaultPropertyValue(inputDef, mergedProperties, dataTypes);
             toscaNodeType.setProperties(mergedProperties);
         }
         // Extracted to method for code reuse
         return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes);
     }
 
+    private void resolveDefaultPropertyValue(List<InputDefinition> inputDef,
+                                             Map<String, ToscaProperty> mergedProperties,
+                                             Map<String, DataTypeDefinition> dataTypes) {
+        for (Map.Entry<String, ToscaProperty> mergedPropertyEntry : mergedProperties.entrySet()) {
+            ToscaProperty value = mergedPropertyEntry.getValue();
+            if (Objects.nonNull(value) && value.getDefaultp() instanceof Map) {
+                Map<String, String> valueAsMap = (Map<String, String>) value.getDefaultp();
+                String inputName = valueAsMap.get(ToscaFunctions.GET_INPUT.getFunctionName());
+                Optional<InputDefinition> matchedInputDefinition = inputDef.stream()
+                        .filter(componentInput -> componentInput.getName().equals(inputName))
+                        .findFirst();
+                if (matchedInputDefinition.isPresent()) {
+                    InputDefinition matchedInput = matchedInputDefinition.get();
+                    Object resolvedDefaultValue = new PropertyConvertor().convertToToscaObject(matchedInput.getType(),
+                            matchedInput.getDefaultValue(), matchedInput.getSchemaType(), dataTypes, false);
+                    value.setDefaultp(resolvedDefaultValue);
+                    mergedProperties.put(mergedPropertyEntry.getKey(), value);
+                }
+            }
+        }
+    }
+
   private void addInputsToProperties(Map<String, DataTypeDefinition> dataTypes,
                                      List<InputDefinition> inputDef,
                                      Map<String, ToscaProperty> mergedProperties) {
@@ -692,12 +698,14 @@ public class ToscaExportHandler {
                 addPropertiesOfParentComponent(dataTypes, originalComponent, props);
             }
 
-            if (null != componentInstancesProperties && componentInstancesProperties.containsKey(instanceUniqueId)) {
+            if (null != componentInstancesProperties && componentInstancesProperties.containsKey(instanceUniqueId)
+                    && !isComponentOfTypeServiceProxy(componentInstance)) {
                 addPropertiesOfComponentInstance(componentInstancesProperties, dataTypes,
                         instanceUniqueId, props);
             }
 
-            if (componentInstancesInputs != null && componentInstancesInputs.containsKey(instanceUniqueId)) {
+            if (componentInstancesInputs != null && componentInstancesInputs.containsKey(instanceUniqueId)
+                    && !isComponentOfTypeServiceProxy(componentInstance)) {
                 addComponentInstanceInputs(dataTypes, componentInstancesInputs, instanceUniqueId,
                         props);
             }
@@ -821,8 +829,8 @@ public class ToscaExportHandler {
         if (instanceInputsList != null) {
             instanceInputsList.forEach(input -> {
 
-                Supplier<String> supplier = () -> input.getValue() != null && !input.getValue().isEmpty()
-                                                          ? input.getValue() : input.getDefaultValue();
+                Supplier<String> supplier = () -> input.getValue() != null && !Objects.isNull(input.getValue())
+                        ? input.getValue() : input.getDefaultValue();
                 propertyConvertor.convertAndAddValue(dataTypes, props, input, supplier);
             });
         }
@@ -844,13 +852,13 @@ public class ToscaExportHandler {
     private void addPropertiesOfParentComponent(Map<String, DataTypeDefinition> dataTypes,
             Component componentOfInstance, Map<String, Object> props) {
 
-        List<PropertyDefinition> componentProperties = ((Resource) componentOfInstance).getProperties();
+        List<PropertyDefinition> componentProperties = componentOfInstance.getProperties();
         if (isNotEmpty(componentProperties)) {
             componentProperties.stream()
-                               // Filters out properties with empty default values
-                               .filter(prop -> isNotEmpty(prop.getDefaultValue()))
-                               // Converts and adds each value to property map
-                               .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop,
+                    // Filters out properties with empty default values
+                               .filter(prop -> StringUtils.isNotEmpty(prop.getDefaultValue()))
+                    // Converts and adds each value to property map
+                    .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop,
                                        prop::getDefaultValue));
         }
     }
index a72f57d..d69e4f6 100644 (file)
 
 package org.openecomp.sdc.be.tosca.utils;
 
-import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.isOperationInputMappedToComponentProperty;
-
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import java.util.ArrayList;
-import java.util.Arrays;
+import com.google.gson.Gson;
+
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+
 import org.apache.commons.collections.MapUtils;
 import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
@@ -33,6 +32,8 @@ import org.openecomp.sdc.be.model.Component;
 import org.openecomp.sdc.be.model.DataTypeDefinition;
 import org.openecomp.sdc.be.model.InterfaceDefinition;
 import org.openecomp.sdc.be.model.Product;
+import org.openecomp.sdc.be.model.tosca.ToscaFunctions;
+import org.openecomp.sdc.be.tosca.PropertyConvertor;
 import org.openecomp.sdc.be.tosca.model.ToscaInterfaceDefinition;
 import org.openecomp.sdc.be.tosca.model.ToscaInterfaceNodeType;
 import org.openecomp.sdc.be.tosca.model.ToscaLifecycleOperationDefinition;
@@ -50,9 +51,7 @@ public class InterfacesOperationsToscaUtil {
     private static final String DOT = ".";
     private static final String DEFAULTP = "defaultp";
 
-    static final String SELF = "SELF";
-    static final String GET_PROPERTY = "get_property";
-    static final String GET_OPERATION_OUTPUT = "get_operation_output";
+    public static final String SELF = "SELF";
 
     private InterfacesOperationsToscaUtil() {
     }
@@ -153,7 +152,7 @@ public class InterfacesOperationsToscaUtil {
                     toscaOperation.setImplementation(operationArtifactPath);
                 }
                 toscaOperation.setDescription(operationEntry.getValue().getDescription());
-                fillToscaOperationInputs(operationEntry.getValue(), toscaOperation, component);
+                fillToscaOperationInputs(operationEntry.getValue(), dataTypes, toscaOperation, isServiceProxyInterface);
 
                 toscaOperations.put(operationEntry.getValue().getName(), toscaOperation);
             }
@@ -162,6 +161,7 @@ public class InterfacesOperationsToscaUtil {
             Map<String, Object> interfaceDefAsMap = getObjectAsMap(toscaInterfaceDefinition);
             Map<String, Object> operationsMap = (Map<String, Object>) interfaceDefAsMap.remove(OPERATIONS_KEY);
             if (isServiceProxyInterface) {
+                //Remove input type and copy default value directly into the proxy node template from the node type
                 handleServiceProxyOperationInputValue(operationsMap, interfaceType);
             } else {
                 handleDefaults(operationsMap);
@@ -235,8 +235,9 @@ public class InterfacesOperationsToscaUtil {
     }
 
     private static void fillToscaOperationInputs(OperationDataDefinition operation,
+                                                 Map<String, DataTypeDefinition> dataTypes,
                                                  ToscaLifecycleOperationDefinition toscaOperation,
-                                                 Component component) {
+                                                 boolean isServiceProxyInterface) {
         if (Objects.isNull(operation.getInputs()) || operation.getInputs().isEmpty()) {
             toscaOperation.setInputs(null);
             return;
@@ -246,61 +247,37 @@ public class InterfacesOperationsToscaUtil {
         for (OperationInputDefinition input : operation.getInputs().getListToscaDataDefinition()) {
             ToscaProperty toscaInput = new ToscaProperty();
             toscaInput.setDescription(input.getDescription());
-            String mappedPropertyName;
-            if (Objects.nonNull(input.getInputId())) {
-                if (isOperationInputMappedToComponentProperty(input, component.getInputs())) {
-                    mappedPropertyName = input.getInputId().substring(input.getInputId().indexOf(DOT) + 1);
-                    toscaInput.setDefaultp(createMappedInputPropertyDefaultValue(mappedPropertyName));
-                } else {
-                    mappedPropertyName = input.getInputId();
-                    toscaInput.setDefaultp(createMappedOutputDefaultValue(mappedPropertyName));
-                }
-            }
             toscaInput.setType(input.getType());
             toscaInput.setRequired(input.isRequired());
+            if (isServiceProxyInterface) {
+                String inputValue = Objects.nonNull(input.getValue()) ? getInputValue(input.getValue()) :
+                        getInputValue(input.getToscaDefaultValue());
+                toscaInput.setDefaultp(new PropertyConvertor().convertToToscaObject(input.getType(),
+                        inputValue, input.getSchemaType(), dataTypes, false));
+            } else {
+                toscaInput.setDefaultp(new PropertyConvertor().convertToToscaObject(input.getType(),
+                        getInputValue(input.getToscaDefaultValue()), input.getSchemaType(), dataTypes, false));
+            }
             toscaInputs.put(input.getName(), toscaInput);
         }
-
         toscaOperation.setInputs(toscaInputs);
     }
 
-    private static Map<String, List<String>> createMappedInputPropertyDefaultValue(String propertyName) {
-        Map<String, List<String>> getPropertyMap = new HashMap<>();
-        List<String> values = new ArrayList<>();
-        values.add(SELF);
-        if (Objects.nonNull(propertyName) && !propertyName.isEmpty()) {
-            values.addAll(Arrays.asList(propertyName.split("\\.")));
-        }
-
-        getPropertyMap.put(GET_PROPERTY, values);
-
-        return getPropertyMap;
-    }
-
-    /**
-     * Create the value for operation input mapped to an operation output.
-     * @param propertyName the mapped other operation output full name
-     * @return input map for tosca
-     */
-    private static Map<String, List<String>> createMappedOutputDefaultValue(String propertyName) {
-        Map<String, List<String>> getOperationOutputMap = new HashMap<>();
-        //For operation input mapped to other operation output parameter, the mapped property value
-        // should be of the format <interface name>.<operation name>.<output parameter name>
-        // Operation name and output param name should not contain "."
-        List<String> defaultMappedOperationOutputValue = new ArrayList<>();
-        String[] tokens = propertyName.split("\\.");
-        if (tokens.length > 2) {
-            defaultMappedOperationOutputValue.add(SELF);
-            String outputPropertyName = tokens[tokens.length - 1];
-            String operationName = tokens[tokens.length - 2];
-            String mappedPropertyInterfaceType =
-                    propertyName.substring(0, propertyName.indexOf(operationName + '.' + outputPropertyName) - 1);
-            String interfaceName =
-                    mappedPropertyInterfaceType.substring(mappedPropertyInterfaceType.lastIndexOf('.') + 1);
-            defaultMappedOperationOutputValue.addAll(Arrays.asList(interfaceName, operationName, outputPropertyName));
-            getOperationOutputMap.put(GET_OPERATION_OUTPUT, defaultMappedOperationOutputValue);
+    private static String getInputValue(String inputValue) {
+        String toscaInputValue = inputValue;
+        if (Objects.nonNull(inputValue) && inputValue.contains(ToscaFunctions.GET_OPERATION_OUTPUT.getFunctionName())) {
+            Gson gson = new Gson();
+            Map<String, List<String>> consumptionValue = gson.fromJson(inputValue, Map.class);
+            List<String> mappedOutputValue =
+                    consumptionValue.get(ToscaFunctions.GET_OPERATION_OUTPUT.getFunctionName());
+            //Extract the interface name from the interface type
+            String interfaceType = mappedOutputValue.get(1);
+            String interfaceName = interfaceType.substring(interfaceType.lastIndexOf('.') + 1);
+            mappedOutputValue.remove(1);
+            mappedOutputValue.add(1, interfaceName);
+            toscaInputValue = gson.toJson(consumptionValue);
         }
-        return getOperationOutputMap;
+        return toscaInputValue;
     }
 
     private static Map<String, Object> getObjectAsMap(Object obj) {
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/types/ServiceConsumptionData.java b/catalog-be/src/main/java/org/openecomp/sdc/be/types/ServiceConsumptionData.java
new file mode 100644 (file)
index 0000000..5e97ac6
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * 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.
+ */
+
+package org.openecomp.sdc.be.types;
+
+public class ServiceConsumptionData {
+  private String inputId;
+  private String source;
+  private String value;
+  private String type;
+
+  public String getInputId() {
+    return inputId;
+  }
+
+  public void setInputId(String inputId) {
+    this.inputId = inputId;
+  }
+
+  public String getSource() {
+    return source;
+  }
+
+  public void setSource(String source) {
+    this.source = source;
+  }
+
+  public String getValue() {
+    return value;
+  }
+
+  public void setValue(String value) {
+    this.value = value;
+  }
+
+  public String getType() {
+    return type;
+  }
+
+  public void setType(String type) {
+    this.type = type;
+  }
+}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/types/ServiceConsumptionSource.java b/catalog-be/src/main/java/org/openecomp/sdc/be/types/ServiceConsumptionSource.java
new file mode 100644 (file)
index 0000000..9e297b7
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * 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.
+ */
+
+package org.openecomp.sdc.be.types;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public enum  ServiceConsumptionSource {
+  SERVICE_INPUT("ServiceInput"),
+  STATIC("Static");
+
+
+  private static Map<String, ServiceConsumptionSource> sourceToValue;
+
+  static {
+    sourceToValue = new HashMap<>();
+    for(ServiceConsumptionSource sourceName : ServiceConsumptionSource.values()) {
+      sourceToValue.put(sourceName.source, sourceName);
+    }
+  }
+
+  private String source;
+
+  ServiceConsumptionSource(String source) {
+    this.source = source;
+  }
+
+  public static ServiceConsumptionSource getSourceValue(String source) {
+    return sourceToValue.get(source);
+  }
+
+  public String getSource() {
+    return source;
+  }
+}
index 0908afc..d9f8ffc 100644 (file)
@@ -2250,10 +2250,16 @@ errors:
         message: "Error: Cannot update or delete interface operation output(s) '%1' mapped to an operation input",
         messageId: "SVC4723"
     }
-#---------SVC4723-----------------------------
+#---------SVC4724-----------------------------
 # %1 - Interface Operation output name
-    INTERFACE_OPERATION_MAPPED_OUTPUT_MODIFIED: {
+    INTERFACE_OPERATION_DELETE_WITH_MAPPED_OUTPUT: {
         code: 400,
-        message: "Error: Cannot update or delete interface operation output(s) '%1' mapped to an operation input",
-        messageId: "SVC4723"
+        message: "Error: Cannot delete interface operation with output(s) '%1' mapped to another operation input",
+        messageId: "SVC4724"
+    }
+#---------SVC4725-----------------------------
+    INVALID_CONSUMPTION_TYPE: {
+        code: 400,
+        message: "Error: Given value is different than input type. Needs to be %1",
+        messageId: "SVC4725"
     }
\ No newline at end of file
index df4ef64..beb3888 100644 (file)
@@ -112,6 +112,9 @@ public class InterfaceOperationBusinessLogicTest {
         when(interfaceOperationValidation
                      .validateInterfaceOperations(anyObject(), anyObject(), any(), anyMap(), anyBoolean()))
                 .thenReturn(Either.left(true));
+        when(interfaceOperationValidation
+                .validateDeleteOperationContainsNoMappedOutput(anyObject(), anyObject(), any()))
+                .thenReturn(Either.left(true));
         when(titanDao.commit()).thenReturn(TitanOperationStatus.OK);
     }
 
index 2e5128c..f94906b 100644 (file)
@@ -16,6 +16,7 @@ import org.openecomp.sdc.be.components.utils.InputsBuilder;
 import org.openecomp.sdc.be.components.utils.ResourceBuilder;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
 import org.openecomp.sdc.be.datatypes.elements.Annotation;
+import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
 import org.openecomp.sdc.be.impl.ComponentsUtils;
 import org.openecomp.sdc.be.model.InputDefinition;
@@ -57,7 +58,8 @@ public class ComponentInstanceInputsRedeclareHandlerTest {
         currContainer = new ResourceBuilder()
                 .addInstanceProperty("inst1", "prop1")
                 .addInstanceProperty("inst1", "prop2")
-                .addInstanceInput("inst2", "prop3")
+                .addInstanceInput("inst1", "prop1", Collections.singletonList(new GetInputValueDataDefinition()))
+                .addInstanceInput("inst1", "prop2", Collections.singletonList(new GetInputValueDataDefinition()))
                 .setUniqueId(RESOURCE_ID)
                 .build();
 
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceInterfacesMergeTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/merge/instance/ComponentInstanceInterfacesMergeTest.java
new file mode 100644 (file)
index 0000000..69caa8e
--- /dev/null
@@ -0,0 +1,116 @@
+package org.openecomp.sdc.be.components.merge.instance;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.when;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.impl.ComponentsUtils;
+import org.openecomp.sdc.be.model.Component;
+import org.openecomp.sdc.be.model.ComponentInstance;
+import org.openecomp.sdc.be.model.ComponentInstanceInterface;
+import org.openecomp.sdc.be.model.InterfaceDefinition;
+import org.openecomp.sdc.be.model.Service;
+import org.openecomp.sdc.be.model.User;
+import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade;
+import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
+import org.openecomp.sdc.common.api.UserRoleEnum;
+import org.openecomp.sdc.test.utils.InterfaceOperationTestUtils;
+
+public class ComponentInstanceInterfacesMergeTest {
+
+  @InjectMocks
+  private ComponentInstanceInterfacesMerge componentInstanceInterfacesMerge;
+
+  @Mock
+  private DataForMergeHolder dataHolder;
+
+  @Mock
+  private ComponentsUtils componentsUtils;
+
+  @Mock
+  private Component containerComponent;
+
+  @Mock
+  private ToscaOperationFacade toscaOperationFacade;
+
+  private Component updatedContainer;
+  private Component origContainer;
+  private Component origComponent;
+  private ComponentInstance currentResourceInstance;
+  private ComponentInstanceInterface origComponentInstanceInterface;
+  private ComponentInstanceInterface newComponentInstanceInterface;
+  private User user;
+
+  @Before
+  public void setUpData() {
+    MockitoAnnotations.initMocks(this);
+    user = new User();
+    user.setUserId("44");
+    user.setRole(UserRoleEnum.ADMIN.getName());
+
+    currentResourceInstance = new ComponentInstance();
+    currentResourceInstance.setUniqueId("TestUniqueID1");
+    currentResourceInstance.setComponentUid("TestUID1");
+
+    origComponent = new Service();
+    origComponent.setUniqueId("TestUniqueID12");
+
+    dataHolder = new DataForMergeHolder();
+    dataHolder.setOrigInstanceNode(origComponent);
+
+    Map<String, InterfaceDefinition> origInterfaceDefinition =
+            InterfaceOperationTestUtils.createMockInterfaceDefinitionMap("Interface1", "Operation1", "Operation1");
+    origComponentInstanceInterface = new ComponentInstanceInterface("TestService1", origInterfaceDefinition.get("Interface1"));
+
+    Map<String, InterfaceDefinition> newInterfaceDefinition =
+            InterfaceOperationTestUtils.createMockInterfaceDefinitionMap("Interface2", "Operation2", "Operation2");
+    newComponentInstanceInterface = new ComponentInstanceInterface("TestService2", newInterfaceDefinition.get("Interface2"));
+
+    when(toscaOperationFacade.updateComponentInstanceInterfaces(any(), anyString())).thenReturn(StorageOperationStatus.OK);
+    when(componentsUtils.convertFromStorageResponse(any())).thenReturn(ActionStatus.OK);
+
+    ComponentInstance componentInstance = new ComponentInstance();
+    componentInstance.setUniqueId("CI_1");
+    componentInstance.setInterfaces((Map) newInterfaceDefinition);
+
+    Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces = new HashMap<>();
+    componentInstanceInterfaces.put(componentInstance.getUniqueId(), Collections.singletonList(newComponentInstanceInterface));
+
+    updatedContainer = new Service();
+    updatedContainer.setComponentInstances(Collections.singletonList(componentInstance));
+    updatedContainer.setComponentInstancesInterfaces(componentInstanceInterfaces);
+
+    origContainer = new Service();
+    origContainer.setComponentInstances(Collections.singletonList(componentInstance));
+    origContainer.setComponentInstancesInterfaces(componentInstanceInterfaces);
+  }
+
+  @Test
+  public void saveDataBeforeMerge() {
+    doReturn(Collections.singletonList(origComponentInstanceInterface)).when(containerComponent).safeGetComponentInstanceInterfaces(any());
+    componentInstanceInterfacesMerge.saveDataBeforeMerge(dataHolder, containerComponent, currentResourceInstance, origComponent);
+    assertEquals(origComponent, dataHolder.getOrigInstanceNode());
+    assertEquals(origComponentInstanceInterface, dataHolder.getOrigComponentInstanceInterfaces().get(0));
+  }
+
+  @Test
+  public void mergeDataAfterCreate() {
+    doReturn(Collections.singletonList(origComponentInstanceInterface)).when(containerComponent).safeGetComponentInstanceInterfaces(any());
+    componentInstanceInterfacesMerge.saveDataBeforeMerge(dataHolder, containerComponent, currentResourceInstance, origComponent);
+    componentInstanceInterfacesMerge.mergeDataAfterCreate(user, dataHolder, updatedContainer, "CI_1");
+    assertEquals(updatedContainer.getComponentInstancesInterfaces().get("CI_1"), origContainer.getComponentInstancesInterfaces().get("CI_1"));
+  }
+}
\ No newline at end of file
index 345e930..c9c9f66 100644 (file)
@@ -98,6 +98,7 @@ public class ComponentInstanceMergeDataBusinessLogicTest {
         assertFalse(value.isIgnoreComponentInstancesProperties());
         assertFalse(value.isIgnoreComponentInstancesInputs());
         assertFalse(value.isIgnoreArtifacts());
+        assertFalse(value.isIgnoreComponentInstancesInterfaces());
     }
 
 
index 7a2cfd5..5752ae2 100644 (file)
@@ -133,7 +133,7 @@ public class ComponentInstancePropertyDeclaratorTest extends PropertyDeclaratorT
         String expectedInputName = generateExpectedInputName(parentProperty, innerProperty);
         InputDefinition input = inputsByName.get(expectedInputName);
         assertThat(input.getType()).isEqualTo(innerProperty.getType());
-        assertThat(input.getValue()).isEqualTo(null);
+        assertThat(input.getValue()).isEqualTo(innerProperty.getValue());
 //        assertThat(input.getDefaultValue()).isEqualTo(innerProperty.getValue());//bug
         assertThat(input.getUniqueId()).isEqualTo(UniqueIdBuilder.buildPropertyUniqueId(RESOURCE_ID, input.getName()));
         assertThat(input.getPropertyId()).isEqualTo(parentProperty.getUniqueId());
@@ -197,7 +197,7 @@ public class ComponentInstancePropertyDeclaratorTest extends PropertyDeclaratorT
     private void verifyCreatedInput(PropertyDataDefinition property, InputDefinition input) {
         assertThat(input.getType()).isEqualTo(property.getType());
         assertThat(input.getName()).isEqualTo(generateExpectedInputName(property));
-        assertThat(input.getValue()).isEqualTo(null);
+        assertThat(input.getValue()).isEqualTo(property.getValue());
         assertThat(input.getDefaultValue()).isEqualTo(property.getValue());
         assertThat(input.getUniqueId()).isEqualTo(UniqueIdBuilder.buildPropertyUniqueId(RESOURCE_ID, input.getName()));
         assertThat(input.getPropertyId()).isEqualTo(property.getUniqueId());
index dd58497..7275814 100644 (file)
@@ -1,6 +1,7 @@
 package org.openecomp.sdc.be.components.utils;
 
 import org.openecomp.sdc.be.dao.utils.MapUtil;
+import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition;
 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
 import org.openecomp.sdc.be.model.*;
 
@@ -135,6 +136,15 @@ public abstract class ComponentBuilder<T extends Component, B extends ComponentB
         return self();
     }
 
+    public ComponentBuilder<T, B> addInstanceInput(String instanceId, String propName, List<GetInputValueDataDefinition> getInputValues) {
+        ComponentInstanceInput componentInstanceInput = new ComponentInstanceInput();
+        componentInstanceInput.setName(propName);
+        componentInstanceInput.setUniqueId(propName);
+        componentInstanceInput.setGetInputValues(getInputValues);
+        this.addInstanceInput(instanceId, componentInstanceInput);
+        return self();
+    }
+
     public ComponentBuilder<T, B> addRelationship(RequirementCapabilityRelDef requirementCapabilityRelDef) {
         if (component.getComponentInstancesRelations() == null) {
             component.setComponentInstancesRelations(new ArrayList<>());
index 8ceac17..43649f6 100644 (file)
@@ -1,7 +1,10 @@
 package org.openecomp.sdc.be.components.utils;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -17,6 +20,8 @@ public class InterfaceOperationUtilsTest {
     private static final String operationId = "operationId";
     private static final String operationName = "createOperation";
     private static final String interfaceId = "interfaceId";
+    private static final String operationId1 = "operationId1";
+    private static final String interfaceId1 = "interfaceId1";
     private static Resource resource;
 
     @Before
@@ -94,4 +99,28 @@ public class InterfaceOperationUtilsTest {
         Assert.assertFalse(operationEntry.isPresent());
     }
 
+    @Test
+    public void testGetInterfaceDefinitionFromOperationIdSuccess() {
+        List<InterfaceDefinition> interfaces = new ArrayList<>();
+        interfaces.add(InterfaceOperationTestUtils.createMockInterface(interfaceId, operationId, operationName));
+        interfaces.add(InterfaceOperationTestUtils.createMockInterface(interfaceId1, operationId1, operationName));
+        Assert.assertTrue(InterfaceOperationUtils.getInterfaceDefinitionFromOperationId(interfaces, operationId)
+                                  .isPresent());
+    }
+
+    @Test
+    public void testGetInterfaceDefinitionFromOperationIdFailure() {
+        List<InterfaceDefinition> interfaces = new ArrayList<>();
+        interfaces.add(InterfaceOperationTestUtils.createMockInterface(interfaceId1, operationId1, operationName));
+        Assert.assertFalse(InterfaceOperationUtils.getInterfaceDefinitionFromOperationId(interfaces, operationId)
+                                  .isPresent());
+    }
+
+    @Test
+    public void testGetInterfaceDefinitionFromOperationIdFailureInterfacesEmpty() {
+        List<InterfaceDefinition> interfaces = new ArrayList<>();
+        Assert.assertFalse(InterfaceOperationUtils.getInterfaceDefinitionFromOperationId(interfaces, operationId)
+                                   .isPresent());
+    }
+
 }
\ No newline at end of file
index fe1e384..29bc8ec 100644 (file)
@@ -480,6 +480,24 @@ public class InterfaceOperationValidationTest {
     }
 
 
+    @Test
+    public void shouldFailValidateDeleteOperationOperationWithMappedOutput() {
+        InterfaceDefinition inputInterfaceDefinition = InterfaceOperationTestUtils.createMockInterface(interfaceType2,
+                operationId, operationType1);
+        InterfaceDefinition inputParamOutputMappedInterface = InterfaceOperationTestUtils.createMockInterface(
+                interfaceType3, operationId, operationType2);
+        inputParamOutputMappedInterface.getOperationsMap().values()
+                .forEach(operation -> operation.getInputs().getListToscaDataDefinition()
+                        .forEach(operationInputDefinition -> operationInputDefinition.setInputId(interfaceType2 +
+                                "." + operationType1 + "." + outputName1)));
+        component.getInterfaces().put(interfaceType3, inputParamOutputMappedInterface);
+        component.getInterfaces().put(interfaceType2, InterfaceOperationTestUtils.createMockInterface(interfaceType2,
+                operationId, operationType1));
+        Assert.assertTrue(interfaceOperationValidationUtilTest.validateDeleteOperationContainsNoMappedOutput(
+                inputInterfaceDefinition.getOperationsMap().get(operationId), component,
+                inputInterfaceDefinition).isRight());
+    }
+
     private InterfaceDefinition createInterfaceOperationData(String uniqueID, String description,
                                                              ArtifactDefinition artifactDefinition,
                                                              ListDataDefinition<OperationInputDefinition> inputs,
index a61ea04..d46d234 100644 (file)
@@ -144,6 +144,8 @@ public class ToscaExportHandlerTest extends BeConfDependentTest {
                Mockito.when(dataTypeCache.getAll()).thenReturn(Either.left(new HashMap<>()));
                Mockito.when(capabiltyRequirementConvertor.convertRequirements(Mockito.any(Map.class), Mockito.any(Resource.class),
                                Mockito.any(ToscaNodeType.class))).thenReturn(Either.left(new ToscaNodeType()));
+               Mockito.when(interfaceLifecycleOperation.getAllInterfaceLifecycleTypes())
+                               .thenReturn(Either.left(Collections.emptyMap()));
 
                // default test when component is Resource
                result = testSubject.exportComponent(component);
@@ -381,7 +383,8 @@ public class ToscaExportHandlerTest extends BeConfDependentTest {
                Either<ToscaTemplate, ToscaError> result;
 
                Mockito.when(dataTypeCache.getAll()).thenReturn(Either.right(TitanOperationStatus.ALREADY_EXIST));
-
+               Mockito.when(interfaceLifecycleOperation.getAllInterfaceLifecycleTypes())
+                               .thenReturn(Either.left(Collections.emptyMap()));
                // default test
                result = Deencapsulation.invoke(testSubject, "convertNodeType",new HashMap<>(), component, toscaNode, nodeTypes);
        }
index fc017c8..3922bc8 100644 (file)
 
 package org.openecomp.sdc.be.tosca.utils;
 
-import static org.openecomp.sdc.be.tosca.utils.InterfacesOperationsToscaUtil.GET_OPERATION_OUTPUT;
-import static org.openecomp.sdc.be.tosca.utils.InterfacesOperationsToscaUtil.GET_PROPERTY;
 import static org.openecomp.sdc.be.tosca.utils.InterfacesOperationsToscaUtil.SELF;
 import static org.openecomp.sdc.be.tosca.utils.InterfacesOperationsToscaUtil.addInterfaceDefinitionElement;
 import static org.openecomp.sdc.be.tosca.utils.InterfacesOperationsToscaUtil.addInterfaceTypeElement;
 
 import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.gson.Gson;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+
 import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.onap.sdc.tosca.services.YamlUtil;
 import org.openecomp.sdc.be.DummyConfigurationManager;
 import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
@@ -39,16 +41,19 @@ import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
 import org.openecomp.sdc.be.datatypes.elements.OperationOutputDefinition;
 import org.openecomp.sdc.be.model.Component;
+import org.openecomp.sdc.be.model.DataTypeDefinition;
 import org.openecomp.sdc.be.model.InputDefinition;
 import org.openecomp.sdc.be.model.InterfaceDefinition;
 import org.openecomp.sdc.be.model.Resource;
 import org.openecomp.sdc.be.model.Service;
+import org.openecomp.sdc.be.model.tosca.ToscaFunctions;
 import org.openecomp.sdc.be.tosca.ToscaExportHandler;
 import org.openecomp.sdc.be.tosca.ToscaRepresentation;
 import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
 import org.openecomp.sdc.be.tosca.model.ToscaTemplate;
 import org.openecomp.sdc.common.util.YamlToObjectConverter;
 
+
 public class InterfacesOperationsToscaUtilTest {
 
     private static final String MAPPED_PROPERTY_NAME = "mapped_property";
@@ -57,6 +62,8 @@ public class InterfacesOperationsToscaUtilTest {
     private static final String NODE_TYPE_NAME = "test";
     private String[] inputTypes = {"string", "integer", "float", "boolean"};
     private static ObjectMapper mapper;
+    private static final Map<String, DataTypeDefinition> dataTypes = new HashMap<>();
+
 
     @BeforeClass
     public static void setUp() {
@@ -122,7 +129,7 @@ public class InterfacesOperationsToscaUtilTest {
         component.setInterfaces(new HashMap<>());
         component.getInterfaces().put(interfaceType, addedInterface);
         ToscaNodeType nodeType = new ToscaNodeType();
-        addInterfaceDefinitionElement(component, nodeType, null, false);
+        addInterfaceDefinitionElement(component, nodeType, dataTypes, false);
 
         ToscaExportHandler handler = new ToscaExportHandler(null,null,null,null,null,null, null);
         ToscaTemplate template = new ToscaTemplate(NODE_TYPE_NAME);
@@ -153,7 +160,7 @@ public class InterfacesOperationsToscaUtilTest {
         component.setInterfaces(new HashMap<>());
         component.getInterfaces().put(interfaceType, addedInterface);
         ToscaNodeType nodeType = new ToscaNodeType();
-        addInterfaceDefinitionElement(component, nodeType, null, false);
+        addInterfaceDefinitionElement(component, nodeType, dataTypes, false);
 
         ToscaExportHandler handler = new ToscaExportHandler(null,null,null,null,null,null, null);
         ToscaTemplate template = new ToscaTemplate("testService");
@@ -172,6 +179,70 @@ public class InterfacesOperationsToscaUtilTest {
         Assert.assertTrue(mainYaml.contains("com.some.service.or.other.serviceName"));
     }
 
+
+    @Test
+    public void testGetInterfaceAsMapServiceProxy() {
+        Component component = new Resource();
+        component.setNormalizedName("normalizedComponentName");
+        InterfaceDefinition addedInterface = new InterfaceDefinition();
+        addedInterface.setToscaResourceName("com.some.resource.or.other.resourceName");
+        addedInterface.setType("com.some.resource.or.other.resourceName");
+        addOperationsToInterface(component, addedInterface, 3, 2, true, false);
+        final String interfaceType = "normalizedComponentName-interface";
+        component.setInterfaces(new HashMap<>());
+        component.getInterfaces().put(interfaceType, addedInterface);
+        Map<String, Object> interfacesMap = InterfacesOperationsToscaUtil
+                .getInterfacesMap(component, component.getInterfaces(), null, false, true);
+        ToscaNodeType nodeType = new ToscaNodeType();
+        nodeType.setInterfaces(interfacesMap);
+        ToscaExportHandler handler = new ToscaExportHandler();
+        ToscaTemplate template = new ToscaTemplate(NODE_TYPE_NAME);
+        Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
+        nodeTypes.put(NODE_TYPE_NAME, nodeType);
+        template.setNode_types(nodeTypes);
+        final ToscaRepresentation toscaRepresentation = handler.createToscaRepresentation(template);
+
+        String mainYaml = toscaRepresentation.getMainYaml();
+        Assert.assertFalse(mainYaml.contains("operations"));
+        Assert.assertTrue(mainYaml.contains("resourceName:"));
+        Assert.assertTrue(mainYaml.contains("inputs:"));
+        validateServiceProxyOperationInputs(mainYaml);
+        Assert.assertFalse(mainYaml.contains("defaultp"));
+        Assert.assertTrue(mainYaml.contains("has description"));
+        Assert.assertTrue(mainYaml.contains(MAPPED_PROPERTY_NAME));
+        Assert.assertTrue(mainYaml.contains("com.some.resource.or.other.resourceName"));
+    }
+
+//    @Test
+//    public void addInterfaceDefinitionElementToService() {
+//        Component component = new Service();
+//        component.setNormalizedName("normalizedServiceComponentName");
+//        InterfaceDefinition addedInterface = new InterfaceDefinition();
+//        addedInterface.setToscaResourceName("com.some.service.or.other.serviceName");
+//
+//        addOperationsToInterface(addedInterface, 3, 2, true);
+//        final String interfaceType = "normalizedServiceComponentName-interface";
+//        component.setInterfaces(new HashMap<>());
+//        component.getInterfaces().put(interfaceType, addedInterface);
+//        ToscaNodeType nodeType = new ToscaNodeType();
+//        InterfacesOperationsToscaUtil.addInterfaceDefinitionElement(component, nodeType);
+//
+//        ToscaExportHandler handler = new ToscaExportHandler();
+//        ToscaTemplate template = new ToscaTemplate("testService");
+//        Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
+//        nodeTypes.put("test", nodeType);
+//        template.setNode_types(nodeTypes);
+//        final ToscaRepresentation toscaRepresentation = handler.createToscaRepresentation(template);
+//
+//        Assert.assertFalse(toscaRepresentation.getMainYaml().contains("operations"));
+//        Assert.assertTrue(toscaRepresentation.getMainYaml().contains("serviceName:"));
+//        Assert.assertTrue(toscaRepresentation.getMainYaml().contains("inputs:"));
+//        Assert.assertFalse(toscaRepresentation.getMainYaml().contains("defaultp"));
+//        Assert.assertTrue(toscaRepresentation.getMainYaml().contains("has description"));
+//        Assert.assertTrue(toscaRepresentation.getMainYaml().contains("naming_function_"));
+//        Assert.assertTrue(toscaRepresentation.getMainYaml().contains("com.some.service.or.other.serviceName"));
+//    }
+
     @Test
     public void addInterfaceDefinitionElement_noInputs() {
         Component component = new Resource();
@@ -218,7 +289,7 @@ public class InterfacesOperationsToscaUtilTest {
         component.setInterfaces(new HashMap<>());
         component.getInterfaces().put(addedInterfaceType, addedInterface);
         ToscaNodeType nodeType = new ToscaNodeType();
-        addInterfaceDefinitionElement(component, nodeType, null, false);
+        addInterfaceDefinitionElement(component, nodeType, dataTypes, false);
 
         ToscaExportHandler handler = new ToscaExportHandler(null,null,null,null,null,null, null);
         ToscaTemplate template = new ToscaTemplate("test");
@@ -226,7 +297,6 @@ public class InterfacesOperationsToscaUtilTest {
         nodeTypes.put("test", nodeType);
         template.setNode_types(nodeTypes);
         final ToscaRepresentation toscaRepresentation = handler.createToscaRepresentation(template);
-
         String mainYaml = toscaRepresentation.getMainYaml();
         Assert.assertFalse(mainYaml.contains("operations"));
         Assert.assertTrue(mainYaml.contains("resourceNameInputMappedToOutput:"));
@@ -243,30 +313,30 @@ public class InterfacesOperationsToscaUtilTest {
         addedInterface.setType(addedInterfaceType);
         addOperationsToInterface(component, addedInterface, 2, 2, true, true);
         addedInterface.getOperationsMap().values().stream()
-                      .filter(operationInputDefinition -> operationInputDefinition.getName().equalsIgnoreCase(
-                              "name_for_op_0"))
-                      .forEach(operation -> operation.getInputs().getListToscaDataDefinition().stream()
-                                                     .filter(opInputDef -> opInputDef.getName().contains("integer"))
-                                                     .forEach(opInputDef -> opInputDef.setInputId(
-                                                             addedInterfaceType +".name_for_op_1.output_integer_1")));
+                .filter(operationInputDefinition -> operationInputDefinition.getName().equalsIgnoreCase(
+                        "name_for_op_0"))
+                .forEach(operation -> operation.getInputs().getListToscaDataDefinition().stream()
+                        .filter(opInputDef -> opInputDef.getName().contains("integer"))
+                        .forEach(opInputDef -> opInputDef.setInputId(
+                                addedInterfaceType +".name_for_op_1.output_integer_1")));
         //Mapping to operation from another interface
         String secondInterfaceType = "org.test.lifecycle.standard.interfaceType.second";
         InterfaceDefinition secondInterface = new InterfaceDefinition();
         secondInterface.setType(secondInterfaceType);
         addOperationsToInterface(component, secondInterface, 2, 2, true, true);
         secondInterface.getOperationsMap().values().stream()
-                      .filter(operationInputDefinition -> operationInputDefinition.getName().equalsIgnoreCase(
-                              "name_for_op_0"))
-                      .forEach(operation -> operation.getInputs().getListToscaDataDefinition().stream()
-                                                     .filter(opInputDef -> opInputDef.getName().contains("integer"))
-                                                     .forEach(opInputDef -> opInputDef.setInputId(
-                                                             addedInterfaceType +".name_for_op_1.output_integer_1")));
+                .filter(operationInputDefinition -> operationInputDefinition.getName().equalsIgnoreCase(
+                        "name_for_op_0"))
+                .forEach(operation -> operation.getInputs().getListToscaDataDefinition().stream()
+                        .filter(opInputDef -> opInputDef.getName().contains("integer"))
+                        .forEach(opInputDef -> opInputDef.setInputId(
+                                addedInterfaceType +".name_for_op_1.output_integer_1")));
         component.setInterfaces(new HashMap<>());
         component.getInterfaces().put(addedInterfaceType, addedInterface);
         component.getInterfaces().put(secondInterfaceType, secondInterface);
 
         ToscaNodeType nodeType = new ToscaNodeType();
-        addInterfaceDefinitionElement(component, nodeType, null,false);
+        addInterfaceDefinitionElement(component, nodeType, dataTypes, false);
 
         ToscaExportHandler handler = new ToscaExportHandler(null,null,null,null,null,null, null);
         ToscaTemplate template = new ToscaTemplate("test");
@@ -289,7 +359,7 @@ public class InterfacesOperationsToscaUtilTest {
         for (int i = 0; i < numOfOps; i++) {
             final OperationDataDefinition operation = new OperationDataDefinition();
             operation.setName("name_for_op_" + i);
-            operation.setDescription( "op "+i+" has description");
+            operation.setDescription("op " + i + " has description");
             final ArtifactDataDefinition implementation = new ArtifactDataDefinition();
             implementation.setArtifactName(i + "_createBPMN.bpmn");
             operation.setImplementation(implementation);
@@ -297,13 +367,13 @@ public class InterfacesOperationsToscaUtilTest {
                 operation.setInputs(createInputs(component, numOfInputsPerOp));
             }
             if (hasOutputs) {
-                operation.setOutputs(createOutputs(numOfInputsPerOp));
+                operation.setOutputs(createOutputs(addedInterface.getToscaResourceName(),
+                        operation.getName(), numOfInputsPerOp));
             }
             addedInterface.getOperations().put(operation.getName(), operation);
         }
     }
 
-
     private ListDataDefinition<OperationInputDefinition> createInputs(Component component, int numOfInputs) {
         ListDataDefinition<OperationInputDefinition> operationInputDefinitionList = new ListDataDefinition<>();
         for (int i = 0; i < numOfInputs; i++) {
@@ -326,10 +396,12 @@ public class InterfacesOperationsToscaUtilTest {
         component.getInputs().add(componentInput);
     }
 
-    private ListDataDefinition<OperationOutputDefinition> createOutputs(int numOfOutputs) {
+    private ListDataDefinition<OperationOutputDefinition> createOutputs(String interfaceName,
+                                                                        String operationName,
+                                                                        int numOfOutputs) {
         ListDataDefinition<OperationOutputDefinition> operationOutputDefinitionList = new ListDataDefinition<>();
         for (int i = 0; i < numOfOutputs; i++) {
-            operationOutputDefinitionList.add(createMockOperationOutputDefinition(
+            operationOutputDefinitionList.add(createMockOperationOutputDefinition(interfaceName, operationName,
                     OUTPUT_NAME_PREFIX + inputTypes[i] + "_" + i, i));
         }
         return operationOutputDefinitionList;
@@ -341,14 +413,29 @@ public class InterfacesOperationsToscaUtilTest {
         operationInputDefinition.setInputId(id);
         operationInputDefinition.setType(inputTypes[index]);
         operationInputDefinition.setRequired(index % 2 == 0);
+        Map<String, List<String>> toscaDefaultValueMap = new HashMap<>();
+        List<String> toscaDefaultValues = new ArrayList<>();
+        toscaDefaultValues.add(SELF);
+        toscaDefaultValues.add(id.substring(id.lastIndexOf('.') + 1));
+        toscaDefaultValueMap.put(ToscaFunctions.GET_PROPERTY.getFunctionName(), toscaDefaultValues);
+        operationInputDefinition.setToscaDefaultValue(new Gson().toJson(toscaDefaultValueMap));
+        operationInputDefinition.setSource("ServiceInput");
         return operationInputDefinition;
     }
 
-    private OperationOutputDefinition createMockOperationOutputDefinition(String name, int index) {
+    private OperationOutputDefinition createMockOperationOutputDefinition(String interfaceName, String operationName,
+                                                                          String outputName, int index) {
         OperationOutputDefinition operationInputDefinition = new OperationOutputDefinition();
-        operationInputDefinition.setName(name);
+        operationInputDefinition.setName(outputName);
         operationInputDefinition.setType(inputTypes[index]);
         operationInputDefinition.setRequired(index % 2 == 0);
+        Map<String, List<String>> toscaDefaultValueMap = new HashMap<>();
+        List<String> toscaDefaultValues = new ArrayList<>();
+        toscaDefaultValues.add(SELF);
+        toscaDefaultValues.add(interfaceName);
+        toscaDefaultValues.add(operationName);
+        toscaDefaultValues.add(outputName);
+        toscaDefaultValueMap.put(ToscaFunctions.GET_OPERATION_OUTPUT.getFunctionName(), toscaDefaultValues);
         return operationInputDefinition;
     }
 
@@ -392,14 +479,14 @@ public class InterfacesOperationsToscaUtilTest {
                                                               String inputType, int index,
                                                               Map<String, Object> inputValueObject) {
         Map<String, Object> mappedInputValue = (Map<String, Object>) inputValueObject.get("default");
-        if(mappedInputValue.containsKey(GET_PROPERTY)) {
+        if(mappedInputValue.containsKey(ToscaFunctions.GET_PROPERTY.getFunctionName())) {
             String mappedPropertyValue = MAPPED_PROPERTY_NAME + index;
-            List<String> mappedPropertyDefaultValue = (List<String>) mappedInputValue.get(GET_PROPERTY);
+            List<String> mappedPropertyDefaultValue = (List<String>) mappedInputValue.get(ToscaFunctions.GET_PROPERTY.getFunctionName());
             Assert.assertEquals(2, mappedPropertyDefaultValue.size());
             Assert.assertTrue(mappedPropertyDefaultValue.contains(SELF));
             Assert.assertTrue(mappedPropertyDefaultValue.contains(mappedPropertyValue));
-        } else if(mappedInputValue.containsKey(GET_OPERATION_OUTPUT)) {
-            List<String> mappedPropertyDefaultValue = (List<String>) mappedInputValue.get(GET_OPERATION_OUTPUT);
+        } else if(mappedInputValue.containsKey(ToscaFunctions.GET_OPERATION_OUTPUT.getFunctionName())) {
+            List<String> mappedPropertyDefaultValue = (List<String>) mappedInputValue.get(ToscaFunctions.GET_OPERATION_OUTPUT.getFunctionName());
             Assert.assertEquals(4, mappedPropertyDefaultValue.size());
             String mappedPropertyValue = OUTPUT_NAME_PREFIX + inputType + "_" + index;
             Assert.assertTrue(mappedPropertyDefaultValue.contains(SELF));
@@ -407,8 +494,31 @@ public class InterfacesOperationsToscaUtilTest {
             Assert.assertTrue(mappedPropertyDefaultValue.contains(operationName));
             Assert.assertTrue(mappedPropertyDefaultValue.contains(mappedPropertyValue));
         } else {
-            Assert.fail("Invalid Tosca function in default value. Allowed values: "+ GET_PROPERTY +
-                    "/"+ GET_OPERATION_OUTPUT);
+            Assert.fail("Invalid Tosca function in default value. Allowed values: "+ ToscaFunctions.GET_PROPERTY.getFunctionName() +
+                    "/"+ ToscaFunctions.GET_OPERATION_OUTPUT.getFunctionName());
+        }
+    }
+
+    private void validateServiceProxyOperationInputs(String mainYaml) {
+        String nodeTypeKey = NODE_TYPE_NAME + ":";
+        String nodeTypesRepresentation = mainYaml.substring(mainYaml.indexOf(nodeTypeKey) + nodeTypeKey.length(),
+                mainYaml.lastIndexOf(MAPPED_PROPERTY_NAME) + MAPPED_PROPERTY_NAME.length());
+        YamlUtil yamlUtil = new YamlUtil();
+        ToscaNodeType toscaNodeType = yamlUtil.yamlToObject(nodeTypesRepresentation, ToscaNodeType.class);
+        for (Object interfaceVal : toscaNodeType.getInterfaces().values()) {
+            Map<String, Object> interfaceDefinition = mapper.convertValue(interfaceVal, Map.class);
+            for (Object operationVal : interfaceDefinition.values()) {
+                if (operationVal instanceof Map) {
+                    Map<String, Object> operation = (Map<String, Object>) mapper.convertValue(operationVal, Map.class);
+                    Map<String, Object> operationInputs = (Map<String, Object>) operation.get("inputs");
+                    for (Object inputValue : operationInputs.values()) {
+                        Map<String, Object> inputValueAsMap = (Map<String, Object>) inputValue;
+                        Assert.assertFalse(inputValueAsMap.keySet().contains("type"));
+                        Assert.assertFalse(inputValueAsMap.keySet().contains("required"));
+                        Assert.assertFalse(inputValueAsMap.keySet().contains("default"));
+                    }
+                }
+            }
         }
     }
 }
index 15a7fa7..49ee297 100644 (file)
@@ -124,14 +124,15 @@ public enum ActionStatus {
 
     //InterfaceOperation
     INTERFACE_OPERATION_NOT_FOUND, INTERFACE_OPERATION_NAME_ALREADY_IN_USE, INTERFACE_OPERATION_NAME_MANDATORY,
-    INTERFACE_OPERATION_NAME_INVALID, INTERFACE_OPERATION_DESCRIPTION_MAX_LENGTH, INTERFACE_OPERATION_INPUT_NAME_ALREADY_IN_USE,
+    INTERFACE_OPERATION_NAME_INVALID, INTERFACE_OPERATION_INPUT_NAME_ALREADY_IN_USE,
     INTERFACE_OPERATION_OUTPUT_NAME_ALREADY_IN_USE, INTERFACE_OPERATION_NOT_DELETED,
-    INTERFACE_OPERATION_MAPPED_OUTPUT_MODIFIED,
+    INTERFACE_OPERATION_MAPPED_OUTPUT_MODIFIED, INTERFACE_OPERATION_DELETE_WITH_MAPPED_OUTPUT,
     INTERFACE_OPERATION_INPUT_NAME_MANDATORY, INTERFACE_OPERATION_OUTPUT_NAME_MANDATORY,
     INTERFACE_OPERATION_INPUT_PROPERTY_NOT_FOUND_IN_COMPONENT, INTERFACE_OPERATION_INVALID_FOR_LOCAL_TYPE,
     INTERFACE_OPERATION_INVALID_FOR_GLOBAL_TYPE,
     PROPERTY_USED_BY_OPERATION, DECLARED_INPUT_USED_BY_OPERATION,
 
+    INVALID_CONSUMPTION_TYPE,
     //NodeFilter
     NODE_FILTER_NOT_FOUND,
     UNSUPPORTED_VALUE_PROVIDED,
index 119888b..2c84f5a 100644 (file)
@@ -7,9 +7,9 @@
  * 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.
@@ -50,7 +50,7 @@ public enum EdgeLabelEnum {
        SERVICE_API_ARTIFACTS,
        FORWARDING_PATH,
        CALCULATED_CAPABILITIES,
-       FULLFILLED_CAPABILITIES, 
+       FULLFILLED_CAPABILITIES,
        CALCULATED_REQUIREMENTS,
        FULLFILLED_REQUIREMENTS,
        LAST_DISTRIBUTION_STATE_MODIFIER,
@@ -64,8 +64,9 @@ public enum EdgeLabelEnum {
        ALLOTTED_OF,
        INTERFACE,
        INTERFACE_OPERATION,
+       INST_INTERFACES,
        NODE_FILTER_TEMPLATE;
-    
+
     /**
         * Returns EdgeLabelEnum according received name
         * @param name
index 9ba7048..288b1ba 100644 (file)
@@ -59,9 +59,10 @@ public enum VertexTypeEnum {
        EXTERNAL_REF                            ("componentInstanceExtRefs",    MapComponentInstanceExternalRefs.class),
        CATALOG_ROOT                ("catalogRoot",                 null),
        ARCHIVE_ROOT                ("archiveRoot",                 null),
-       INTERFACE               ("interface",                   InterfaceDataDefinition.class),
+       INTERFACE                           ("interface",                               InterfaceDataDefinition.class),
        INTERFACE_OPERATION                     ("interfaceOperation",                  OperationDataDefinition.class),
-       NODE_FILTER_TEMPLATE            ("NodeTemplateFilter", CINodeFilterDataDefinition.class),;
+       NODE_FILTER_TEMPLATE            ("NodeTemplateFilter",          CINodeFilterDataDefinition.class),
+       INST_INTERFACES             ("InstInterfaces",              MapInterfaceDataDefinition.class);
 
        private String name;
        private Class classOfJson;
index c75f22c..fc3eb69 100644 (file)
@@ -41,6 +41,7 @@ public class ComponentInstance extends ComponentInstanceDataDefinition implement
     private Map<String, Object> interfaces;
     private List<PropertyDefinition> properties;
     private CINodeFilterDataDefinition nodeFilter;
+    private List<InputDefinition> inputs;
 
     public ComponentInstance() {
         super();
@@ -145,7 +146,11 @@ public class ComponentInstance extends ComponentInstanceDataDefinition implement
         this.nodeFilter = nodeFilter;
     }
 
+    public List<InputDefinition> getInputs() {
+        return inputs;
+    }
 
-
-
+    public void setInputs(List<InputDefinition> inputs) {
+        this.inputs = inputs;
+    }
 }
index 087816c..35b4a86 100644 (file)
@@ -40,6 +40,7 @@ public class ComponentParametersView {
     private boolean ignoreAdditionalInformation = false;
     private boolean ignoreArtifacts = false;
     private boolean ignoreInterfaces = false;
+    private boolean ignoreComponentInstancesInterfaces = false;
     private boolean ignoreDerivedFrom = false;
     private boolean ignoreAttributesFrom = false;
     private boolean ignoreComponentInstancesAttributesFrom = false;
@@ -147,6 +148,10 @@ public class ComponentParametersView {
                 case NODE_FILTER:
                     this.setIgnoreNodeFilter(false);
                     break;
+                case COMPONENT_INSTANCES_INTERFACES:
+                    this.setIgnoreComponentInstances(false);
+                    this.setIgnoreComponentInstancesInterfaces(false);
+                    break;
                 default:
                     break;
             }
@@ -351,6 +356,14 @@ public class ComponentParametersView {
         this.ignoreInterfaces = ignoreInterfaces;
     }
 
+    public boolean isIgnoreComponentInstancesInterfaces() {
+        return ignoreComponentInstancesInterfaces;
+    }
+
+    public void setIgnoreComponentInstancesInterfaces(boolean ignoreComponentInstancesInterfaces) {
+        this.ignoreComponentInstancesInterfaces = ignoreComponentInstancesInterfaces;
+    }
+
     public boolean isIgnoreAttributesFrom() {
         return ignoreAttributesFrom;
     }
index 04cc6ea..14b7a2f 100644 (file)
@@ -25,7 +25,6 @@ import org.openecomp.sdc.be.datatypes.elements.*;
 import org.openecomp.sdc.be.datatypes.elements.MapCapabilityProperty;
 import org.openecomp.sdc.be.datatypes.elements.MapListCapabilityDataDefinition;
 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
-import org.openecomp.sdc.be.model.MapInterfaceDataDefinition;
 import org.openecomp.sdc.be.model.MapInterfaceInstanceDataDefinition;
 import org.openecomp.sdc.be.model.jsontitan.enums.JsonConstantKeysEnum;
 
index 3e91d74..3bb5e13 100644 (file)
@@ -38,15 +38,48 @@ import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
 import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
 import org.openecomp.sdc.be.dao.jsongraph.utils.JsonParserUtils;
 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
-import org.openecomp.sdc.be.datatypes.elements.*;
+import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.ComponentInstanceDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.CompositionDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.GroupInstanceDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.ListCapabilityDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.ListRequirementDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.MapArtifactDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.MapCapabilityProperty;
+import org.openecomp.sdc.be.datatypes.elements.MapDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.MapGroupsDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.MapInterfaceDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.MapListCapabilityDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.MapListRequirementDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.MapPropertiesDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.RelationshipInstDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.RequirementDataDefinition;
 import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
-import org.openecomp.sdc.be.model.*;
+import org.openecomp.sdc.be.model.ArtifactDefinition;
+import org.openecomp.sdc.be.model.CapabilityDefinition;
+import org.openecomp.sdc.be.model.CapabilityRequirementRelationship;
+import org.openecomp.sdc.be.model.Component;
+import org.openecomp.sdc.be.model.ComponentInstance;
+import org.openecomp.sdc.be.model.ComponentInstanceInput;
+import org.openecomp.sdc.be.model.ComponentInstanceProperty;
+import org.openecomp.sdc.be.model.ComponentParametersView;
+import org.openecomp.sdc.be.model.GroupDefinition;
+import org.openecomp.sdc.be.model.GroupInstance;
+import org.openecomp.sdc.be.model.InputDefinition;
+import org.openecomp.sdc.be.model.PropertyDefinition;
+import org.openecomp.sdc.be.model.RelationshipImpl;
+import org.openecomp.sdc.be.model.RelationshipInfo;
+import org.openecomp.sdc.be.model.RequirementCapabilityRelDef;
+import org.openecomp.sdc.be.model.RequirementDefinition;
+import org.openecomp.sdc.be.model.User;
 import org.openecomp.sdc.be.model.jsontitan.datamodel.NodeType;
 import org.openecomp.sdc.be.model.jsontitan.datamodel.TopologyTemplate;
 import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement;
@@ -145,6 +178,16 @@ public class NodeTemplateOperation extends BaseOperation {
                   return result;
                 }
 
+                result = addServiceInstanceInputsToProxyServiceInstance(updatedContainer, componentInstance);
+                if(result.isRight()) {
+                    return result;
+                }
+
+                result = addServiceInstanceInterfacesToProxyServiceInstance(updatedContainer, componentInstance);
+                if(result.isRight()) {
+                    return result;
+                }
+
             }
         }
         if (result == null) {
@@ -285,8 +328,9 @@ public class NodeTemplateOperation extends BaseOperation {
         List<PropertyDefinition> propertiesList = componentInstance.getProperties();
 
         if (propertiesList != null && !propertiesList.isEmpty()) {
-            Map<String, PropertyDataDefinition> propertiesMap = propertiesList.stream().map(i -> new PropertyDataDefinition(i))
-                                                                              .collect(Collectors.toMap(i -> i.getName(), i -> i));
+            Map<String, PropertyDataDefinition> propertiesMap = propertiesList.stream().map(PropertyDataDefinition::new)
+                                                                              .collect(Collectors.toMap(
+                                                                                      PropertyDataDefinition::getName, i -> i));
             MapPropertiesDataDefinition instProperties = new MapPropertiesDataDefinition(propertiesMap);
             Map<String, MapPropertiesDataDefinition> instPropertiesMap = new HashMap<>();
             instPropertiesMap.put(componentInstance.getUniqueId(), instProperties);
@@ -308,8 +352,58 @@ public class NodeTemplateOperation extends BaseOperation {
         return Either.left(new ImmutablePair<>(updatedContainer, componentInstance.getUniqueId()));
     }
 
-    public Either<TopologyTemplate, StorageOperationStatus> addComponentInstanceToTopologyTemplate(TopologyTemplate container, ToscaElement originToscaElement, ComponentInstanceDataDefinition componentInstance, GraphVertex metadataVertex,
-            boolean allowDeleted, User user) {
+    private Either<ImmutablePair<TopologyTemplate, String>, StorageOperationStatus> addServiceInstanceInputsToProxyServiceInstance(TopologyTemplate updatedContainer, ComponentInstance componentInstance) {
+
+        List<InputDefinition> inputsList = componentInstance.getInputs();
+
+        if (CollectionUtils.isNotEmpty(inputsList)) {
+            Map<String, PropertyDataDefinition> inputsMap = inputsList.stream().map(
+                    PropertyDataDefinition::new).collect(Collectors.toMap(PropertyDataDefinition::getName, i -> i));
+            MapPropertiesDataDefinition instInputs = new MapPropertiesDataDefinition(inputsMap);
+            Map<String, MapPropertiesDataDefinition> instInputsMap = new HashMap<>();
+            instInputsMap.put(componentInstance.getUniqueId(), instInputs);
+            updatedContainer.setInstInputs(instInputsMap);
+
+            StorageOperationStatus status =
+                    addToscaDataDeepElementsBlockToToscaElement(updatedContainer.getUniqueId(),
+                            EdgeLabelEnum.INST_INPUTS, VertexTypeEnum.INST_INPUTS, instInputs,
+                            componentInstance.getUniqueId());
+            if(status != StorageOperationStatus.OK) {
+                return Either.right(status);
+            }
+        }
+
+        return Either.left(new ImmutablePair<>(updatedContainer, componentInstance.getUniqueId()));
+    }
+
+    private Either<ImmutablePair<TopologyTemplate, String>, StorageOperationStatus> addServiceInstanceInterfacesToProxyServiceInstance(TopologyTemplate updatedContainer, ComponentInstance componentInstance) {
+        Map<String, Object> interfaces = componentInstance.getInterfaces();
+
+        if(interfaces != null && !interfaces.isEmpty()) {
+            Map<String, InterfaceDataDefinition> interfacesMap = interfaces.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> (InterfaceDataDefinition) e.getValue()));
+            MapInterfaceDataDefinition instIntrefaces = new MapInterfaceDataDefinition(interfacesMap);
+
+            Map<String, MapInterfaceDataDefinition> instInterfacesMap = new HashMap<>();
+            instInterfacesMap.put(componentInstance.getUniqueId(), instIntrefaces);
+            updatedContainer.setComponentInstInterfaces(instInterfacesMap);
+
+            StorageOperationStatus status =
+                    addToscaDataDeepElementsBlockToToscaElement(updatedContainer.getUniqueId(),
+                            EdgeLabelEnum.INST_INTERFACES, VertexTypeEnum.INST_INTERFACES, instIntrefaces,
+                            componentInstance.getUniqueId());
+
+            if(status != StorageOperationStatus.OK) {
+                return Either.right(status);
+            }
+        }
+
+        return Either.left(new ImmutablePair<>(updatedContainer, componentInstance.getUniqueId()));
+    }
+
+    public Either<TopologyTemplate, StorageOperationStatus> addComponentInstanceToTopologyTemplate(
+            TopologyTemplate container, ToscaElement originToscaElement,
+            ComponentInstanceDataDefinition componentInstance, GraphVertex metadataVertex, boolean allowDeleted,
+            User user) {
 
         Either<TopologyTemplate, StorageOperationStatus> result = null;
         Either<ToscaElement, StorageOperationStatus> updateContainerComponentRes = null;
@@ -615,6 +709,14 @@ public class NodeTemplateOperation extends BaseOperation {
             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to remove instance external refs  for instance {} in container {}. error {] ", componentInstanceId, containerV.getUniqueId(), status);
             return status;
         }
+        status = deleteToscaDataDeepElementsBlockToToscaElement(containerV, EdgeLabelEnum.INST_INTERFACES,
+                VertexTypeEnum.INST_INTERFACES, componentInstanceId);
+        if (status != StorageOperationStatus.OK && status != StorageOperationStatus.NOT_FOUND) {
+            CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG,
+                    "Failed to remove service instance interfaces  for instance {} in container {}. " +
+                            "error {] ", componentInstanceId, containerV.getUniqueId(), status);
+            return status;
+        }
         return StorageOperationStatus.OK;
     }
 
@@ -623,7 +725,7 @@ public class NodeTemplateOperation extends BaseOperation {
         Either<GraphVertex, StorageOperationStatus> result;
         StorageOperationStatus status;
         if (originToscaElement.getToscaType() == ToscaElementTypeEnum.NODE_TYPE) {
-            status = addComponentInstanceToscaDataToNodeTypeContainer((NodeType) originToscaElement, componentInstance, updatedContainerVertex, user, HEAT_VF_ENV_NAME);
+            status = addComponentInstanceToscaDataToNodeTypeContainer((NodeType) originToscaElement, componentInstance, updatedContainerVertex);
         } else {
             status = addComponentInstanceToscaDataToTopologyTemplateContainer((TopologyTemplate) originToscaElement, componentInstance, updatedContainerVertex);
         }
@@ -838,22 +940,29 @@ public class NodeTemplateOperation extends BaseOperation {
         }
         return StorageOperationStatus.OK;
     }
+    private StorageOperationStatus addComponentInstanceToscaDataToNodeTypeContainer(NodeType originNodeType,
+            ComponentInstanceDataDefinition componentInstance, GraphVertex updatedContainerVertex) {
 
-    private StorageOperationStatus addComponentInstanceToscaDataToNodeTypeContainer(NodeType originNodeType, ComponentInstanceDataDefinition componentInstance, GraphVertex updatedContainerVertex, User user, String envType) {
-
-        MapPropertiesDataDefinition instProperties = new MapPropertiesDataDefinition(originNodeType.getProperties());
+        StorageOperationStatus status;
 
-        StorageOperationStatus status = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, EdgeLabelEnum.INST_PROPERTIES, VertexTypeEnum.INST_PROPERTIES, instProperties, componentInstance.getUniqueId());
-        if (status != StorageOperationStatus.OK) {
-            return status;
+        if(MapUtils.isNotEmpty(originNodeType.getProperties())){
+            MapPropertiesDataDefinition instProperties =
+                    new MapPropertiesDataDefinition(originNodeType.getProperties());
+            status = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, EdgeLabelEnum.INST_PROPERTIES,
+                    VertexTypeEnum.INST_PROPERTIES, instProperties, componentInstance.getUniqueId());
+            if (status != StorageOperationStatus.OK) {
+                return status;
+            }
         }
 
-        MapPropertiesDataDefinition instAttributes = new MapPropertiesDataDefinition(originNodeType.getAttributes());
-
-        status = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, EdgeLabelEnum.INST_ATTRIBUTES, VertexTypeEnum.INST_ATTRIBUTES, instAttributes, componentInstance.getUniqueId());
-
-        if (status != StorageOperationStatus.OK) {
-            return status;
+        if(MapUtils.isNotEmpty(originNodeType.getAttributes())){
+            MapPropertiesDataDefinition instAttributes =
+                    new MapPropertiesDataDefinition(originNodeType.getAttributes());
+            status = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, EdgeLabelEnum.INST_ATTRIBUTES,
+                    VertexTypeEnum.INST_ATTRIBUTES, instAttributes, componentInstance.getUniqueId());
+            if (status != StorageOperationStatus.OK) {
+                return status;
+            }
         }
 
         return addCalculatedCapReqFromNodeType(originNodeType, componentInstance, updatedContainerVertex);
index 0954257..4175773 100644 (file)
@@ -56,6 +56,7 @@ import org.openecomp.sdc.be.datatypes.elements.MapArtifactDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.MapCapabilityProperty;
 import org.openecomp.sdc.be.datatypes.elements.MapDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.MapGroupsDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.MapInterfaceDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.MapListCapabilityDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.MapListRequirementDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.MapPropertiesDataDefinition;
@@ -71,6 +72,7 @@ import org.openecomp.sdc.be.model.ComponentInstanceProperty;
 import org.openecomp.sdc.be.model.ComponentParametersView;
 import org.openecomp.sdc.be.model.DistributionStatusEnum;
 import org.openecomp.sdc.be.model.GroupDefinition;
+
 import org.openecomp.sdc.be.model.PolicyDefinition;
 import org.openecomp.sdc.be.model.User;
 import org.openecomp.sdc.be.model.category.CategoryDefinition;
@@ -768,6 +770,13 @@ public class TopologyTemplateOperation extends ToscaElementOperation {
             }
         }
 
+        if (!componentParametersView.isIgnoreComponentInstancesInterfaces()) {
+            TitanOperationStatus storageStatus =
+                    setComponentInstancesInterfacesFromGraph(componentV, toscaElement);
+            if (storageStatus != TitanOperationStatus.OK) {
+                return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(storageStatus));
+            }
+        }
         return Either.left(toscaElement);
     }
 
@@ -795,6 +804,22 @@ public class TopologyTemplateOperation extends ToscaElementOperation {
         return TitanOperationStatus.OK;
     }
 
+
+    private TitanOperationStatus setComponentInstancesInterfacesFromGraph(GraphVertex componentV,
+                                                                          TopologyTemplate topologyTemplate) {
+        Either<Map<String, MapInterfaceDataDefinition>, TitanOperationStatus> result =
+                getDataFromGraph(componentV, EdgeLabelEnum.INST_INTERFACES);
+        if (result.isLeft()) {
+            result.left().value().entrySet().forEach(entry -> topologyTemplate
+                    .addComponentInstanceInterfaceMap(entry.getKey(), entry.getValue()));
+        } else {
+            if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
+                return result.right().value();
+            }
+        }
+        return TitanOperationStatus.OK;
+    }
+
     private StorageOperationStatus associateInterfacesToComponent(GraphVertex topologyTemplateVertex, TopologyTemplate topologyTemplate) {
         Map<String, InterfaceDataDefinition> interfaceMap = topologyTemplate.getInterfaces();
         if (interfaceMap != null && !interfaceMap.isEmpty()) {
@@ -1182,16 +1207,20 @@ public class TopologyTemplateOperation extends ToscaElementOperation {
         if (status != TitanOperationStatus.OK) {
             log.debug("Failed to disassociate requirements for {} error {}",
                     toscaElementVertex.getUniqueId(), status);
-            Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
+            return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
         }
         status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT,
                 EdgeLabelEnum.CAPABILITIES);
         if (status != TitanOperationStatus.OK) {
             log.debug("Failed to disassociate capabilities for {} error {}",
                     toscaElementVertex.getUniqueId(), status);
-            Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
+            return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
+        }
+        status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT, EdgeLabelEnum.INST_INTERFACES);
+        if (status != TitanOperationStatus.OK) {
+            log.debug("Failed to disassociate instances interfaces for {} error {}", toscaElementVertex.getUniqueId(), status);
+            return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
         }
-
         toscaElementVertex.getVertex().remove();
         log.trace("Tosca element vertex for {} was removed", toscaElementVertex.getUniqueId());
 
@@ -1349,6 +1378,16 @@ public class TopologyTemplateOperation extends ToscaElementOperation {
         return updateToscaDataDeepElementsBlockToToscaElement(containerComponent.getUniqueId(), EdgeLabelEnum.CALCULATED_CAP_PROPERTIES, instanceProperties, componentInstanceId);
     }
 
+    public StorageOperationStatus updateComponentInstanceInterfaces(Component containerComponent,
+                                                                    String componentInstanceId,
+                                                                    MapInterfaceDataDefinition instanceInterfaces) {
+        if (MapUtils.isNotEmpty(instanceInterfaces.getMapToscaDataDefinition())) {
+            return updateToscaDataDeepElementsBlockToToscaElement(containerComponent.getUniqueId(),
+                    EdgeLabelEnum.INST_INTERFACES, instanceInterfaces, componentInstanceId);
+        }
+        return StorageOperationStatus.OK;
+    }
+
 
     private boolean isNotEmptyMapOfProperties(String instanceId, Map<String, MapCapabilityProperty> mapPropertiesDataDefinition) {
         return MapUtils.isNotEmpty(mapPropertiesDataDefinition) &&
index a69c80c..9e1e001 100644 (file)
@@ -34,6 +34,7 @@ import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
 import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
 import org.openecomp.sdc.be.datatypes.elements.*;
+import org.openecomp.sdc.be.datatypes.elements.MapInterfaceDataDefinition;
 import org.openecomp.sdc.be.datatypes.enums.*;
 import org.openecomp.sdc.be.model.*;
 import org.openecomp.sdc.be.model.catalog.CatalogComponent;
@@ -2296,6 +2297,13 @@ public class ToscaOperationFacade {
                 .orElse(StorageOperationStatus.NOT_FOUND);
     }
 
+    public StorageOperationStatus updateComponentInstanceInterfaces(Component containerComponent, String componentInstanceUniqueId) {
+        MapInterfaceDataDefinition mapInterfaceDataDefinition =
+                convertComponentInstanceInterfaces(containerComponent, componentInstanceUniqueId);
+        return topologyTemplateOperation
+                .updateComponentInstanceInterfaces(containerComponent, componentInstanceUniqueId, mapInterfaceDataDefinition);
+    }
+
        public StorageOperationStatus updateComponentCalculatedCapabilitiesProperties(Component containerComponent) {
                Map<String, MapCapabilityProperty> mapCapabiltyPropertyMap =
         convertComponentCapabilitiesProperties(containerComponent);
index 6fbd7ad..31a445a 100644 (file)
@@ -29,6 +29,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
 import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
 import org.openecomp.sdc.be.datatypes.elements.*;
+import org.openecomp.sdc.be.datatypes.elements.MapInterfaceDataDefinition;
 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
@@ -279,6 +280,8 @@ public class ModelConverter {
 
             setComponentInstancesArtifactsToComponent(topologyTemplate, component);
 
+            setComponentInstancesInterfacesToComponent(topologyTemplate, component);
+
         }
     }
 
@@ -1182,6 +1185,10 @@ public class ModelConverter {
                 List<PropertyDefinition> instanceProps = topologyTemplate.getInstProperties().get(key).getMapToscaDataDefinition().entrySet().stream().map(e -> new PropertyDefinition(e.getValue())).collect(Collectors.toList());
                 currComponentInstance.setProperties(instanceProps);
             }
+            if(topologyTemplate.getInstInputs() != null && topologyTemplate.getInstInputs().containsKey(key) && topologyTemplate.getInstInputs().get(key) != null ){
+                List<InputDefinition> instanceInputs = topologyTemplate.getInstInputs().get(key).getMapToscaDataDefinition().entrySet().stream().map(e -> new InputDefinition(e.getValue())).collect(Collectors.toList());
+                currComponentInstance.setInputs(instanceInputs);
+            }
             if(topologyTemplate.getComponentInstInterfaces() != null && topologyTemplate.getComponentInstInterfaces().containsKey(key) && topologyTemplate.getComponentInstInterfaces().get(key) != null ){
                 Map<String, Object> interfacesMap = topologyTemplate.getComponentInstInterfaces().get(key).getMapToscaDataDefinition().entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
                 currComponentInstance.setInterfaces(interfacesMap);
index c842e5b..ab2eb03 100644 (file)
@@ -7,9 +7,9 @@
  * 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.
@@ -909,21 +909,18 @@ public class InterfaceLifecycleOperation implements IInterfaceLifecycleOperation
             .collect(Collectors.toList());
 
         for (InterfaceDefinition interfaceDefinition : interfaceDefinitions) {
-
-                Either<List<ImmutablePair<OperationData, GraphEdge>>, TitanOperationStatus>
+            Either<List<ImmutablePair<OperationData, GraphEdge>>, TitanOperationStatus>
                     childrenNodes = titanGenericDao.getChildrenNodes(GraphPropertiesDictionary.UNIQUE_ID.getProperty(),
                     interfaceDefinition.getUniqueId(), GraphEdgeLabels.INTERFACE_OPERATION, NodeTypeEnum.InterfaceOperation, OperationData.class);
-                if(childrenNodes.isRight()) {
-                    return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(childrenNodes.right().value()));
-                }
-
+            if (childrenNodes.isLeft()) {
                 Map<String, OperationDataDefinition> operationsDataDefinitionMap = new HashMap<>();
                 for(ImmutablePair<OperationData, GraphEdge> operation : childrenNodes.left().value()) {
                     OperationData operationData = operation.getLeft();
                     operationsDataDefinitionMap.put(operationData.getUniqueId(), operationData.getOperationDataDefinition());
                 }
                 interfaceDefinition.setOperations(operationsDataDefinitionMap);
-                interfaceTypes.put(interfaceDefinition.getUniqueId(), interfaceDefinition);
+            }
+            interfaceTypes.put(interfaceDefinition.getUniqueId(), interfaceDefinition);
         }
         return Either.left(interfaceTypes);
     }
index 36e5148..1f55fec 100644 (file)
@@ -6,7 +6,8 @@ package org.openecomp.sdc.be.model.tosca;
 public enum ToscaFunctions {
 
     GET_INPUT("get_input"),
-    GET_PROPERTY("get_property");
+    GET_PROPERTY("get_property"),
+    GET_OPERATION_OUTPUT("get_operation_output");
 
     private String functionName;
 
index a8a2409..4272a5c 100644 (file)
@@ -28,11 +28,13 @@ import org.openecomp.sdc.be.model.ArtifactDefinition;
 import org.openecomp.sdc.be.model.CapabilityDefinition;
 import org.openecomp.sdc.be.model.ComponentInstance;
 import org.openecomp.sdc.be.model.ComponentInstanceInput;
+import org.openecomp.sdc.be.model.ComponentInstanceInterface;
 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
 import org.openecomp.sdc.be.model.GroupDefinition;
 import org.openecomp.sdc.be.model.InputDefinition;
 import org.openecomp.sdc.be.model.InterfaceDefinition;
 import org.openecomp.sdc.be.model.PolicyDefinition;
+import org.openecomp.sdc.be.model.PropertyDefinition;
 import org.openecomp.sdc.be.model.RequirementCapabilityRelDef;
 import org.openecomp.sdc.be.model.RequirementDefinition;
 import org.openecomp.sdc.be.model.category.CategoryDefinition;
@@ -84,6 +86,8 @@ public class UiComponentDataTransfer {
     private Map<String, CINodeFilterDataDefinition> nodeFilter;
 
     private Map<String, UINodeFilter> nodeFilterforNode;
+    private List<PropertyDefinition> properties;
+    private Map<String, List<ComponentInstanceInterface>> componentInstancesInterfaces;
 
     public Map<String, InterfaceDefinition> getInterfaces() {
         return interfaces;
@@ -309,4 +313,22 @@ public class UiComponentDataTransfer {
     public void setNodeFilterData(Map<String, UINodeFilter> nodeFilterforNode) {
         this.nodeFilterforNode = nodeFilterforNode;
     }
+
+    public List<PropertyDefinition> getProperties() {
+        return properties;
+    }
+
+    public void setProperties(List<PropertyDefinition> properties) {
+        this.properties = properties;
+    }
+
+    public Map<String, List<ComponentInstanceInterface>> getComponentInstancesInterfaces() {
+        return componentInstancesInterfaces;
+    }
+
+    public void setComponentInstancesInterfaces(
+            Map<String, List<ComponentInstanceInterface>> componentInstancesInterfaces) {
+        this.componentInstancesInterfaces = componentInstancesInterfaces;
+    }
+
 }
index b3afd96..b3c3b67 100644 (file)
 package org.openecomp.sdc.be.ui.model;
 
 import org.openecomp.sdc.be.model.AdditionalInformationDefinition;
+import org.openecomp.sdc.be.model.InterfaceDefinition;
 import org.openecomp.sdc.be.model.PropertyDefinition;
 
 import java.util.List;
+import java.util.Map;
 
 public class UiResourceDataTransfer extends UiComponentDataTransfer{
 
@@ -37,6 +39,7 @@ public class UiResourceDataTransfer extends UiComponentDataTransfer{
 
     private List<PropertyDefinition> attributes;
 
+    private Map<String, InterfaceDefinition> interfaces;
 
     private List<String> defaultCapabilities;
 
@@ -91,6 +94,14 @@ public class UiResourceDataTransfer extends UiComponentDataTransfer{
         this.attributes = attributes;
     }
 
+    public Map<String, InterfaceDefinition> getInterfaces() {
+        return interfaces;
+    }
+
+    public void setInterfaces(Map<String, InterfaceDefinition> interfaces) {
+        this.interfaces = interfaces;
+    }
+
     public List<String> getDefaultCapabilities() {
         return defaultCapabilities;
     }
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/MapInterfaceDataDefinition.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/MapInterfaceDataDefinition.java
new file mode 100644 (file)
index 0000000..7b1b43e
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * 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.
+ */
+
+package org.openecomp.sdc.be.datatypes.elements;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+
+import java.util.Map;
+
+public class MapInterfaceDataDefinition extends MapDataDefinition<InterfaceDataDefinition> {
+
+  public MapInterfaceDataDefinition() {
+
+  }
+
+  @JsonCreator
+  public MapInterfaceDataDefinition(Map<String, InterfaceDataDefinition > mapToscaDataDefinition) {
+    super(mapToscaDataDefinition);
+  }
+
+  @JsonValue
+  @Override
+  public Map<String, InterfaceDataDefinition> getMapToscaDataDefinition() {
+    return mapToscaDataDefinition;
+  }
+}
index 35b760a..1e8ef50 100644 (file)
 package org.openecomp.sdc.be.datatypes.elements;
 
 
-
 import com.fasterxml.jackson.annotation.JsonCreator;
+
 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
 
 
 public class OperationInputDefinition extends InputDataDefinition {
+    private String source;
+    private String sourceProperty;
+    private String toscaDefaultValue;
 
     @JsonCreator
     public OperationInputDefinition() {
         super();
     }
 
-    public OperationInputDefinition(String name, InputDataDefinition inputDefinition) {
+    public OperationInputDefinition(String name, InputDataDefinition inputDefinition, String source, String sourceProperty) {
         super(inputDefinition);
         setName(name);
+        setSource(source);
+        setSourceProperty(sourceProperty);
     }
 
-    public OperationInputDefinition(String name, String property,  Boolean mandatory, String type) {
+    public OperationInputDefinition(String name, String property, Boolean mandatory, String type) {
         super();
         setName(name);
         setInputId(property);
@@ -49,4 +54,27 @@ public class OperationInputDefinition extends InputDataDefinition {
         setToscaPresentationValue(JsonPresentationFields.ARTIFACT_LABEL, name);
     }
 
+    public String getSource() {
+        return source;
+    }
+
+    public void setSource(String source) {
+        this.source = source;
+    }
+
+    public String getSourceProperty() {
+        return sourceProperty;
+    }
+
+    public void setSourceProperty(String sourceProperty) {
+        this.sourceProperty = sourceProperty;
+    }
+
+    public String getToscaDefaultValue() {
+        return toscaDefaultValue;
+    }
+
+    public void setToscaDefaultValue(String toscaDefaultValue) {
+        this.toscaDefaultValue = toscaDefaultValue;
+    }
 }
index abc426c..a0843eb 100644 (file)
@@ -44,7 +44,8 @@ public enum ComponentFieldsEnum {
     FORWARDING_PATHS("forwardingPaths"),
     POLICIES("policies"),
     NON_EXCLUDED_POLICIES("nonExcludedPolicies"),
-    NODE_FILTER("nodeFilter")
+    NODE_FILTER("nodeFilter"),
+    COMPONENT_INSTANCES_INTERFACES("componentInstancesInterfaces")
     ;
 
 
index a72984a..fa4afe1 100644 (file)
@@ -224,12 +224,18 @@ public enum JsonPresentationFields {
     IO_WORKFLOW_ID("workflowId", null),
     IO_WORKFLOW_VERSION_ID("workflowVersionId", null),
     IO_WORKFLOW_ASSOCIATION_TYPE("workflowAssociationType", null),
+
+    //Interface
     INTERFACES("interfaces", null),
     OPERATIONS("operations", null),
     OPERATION_IMPLEMENTATION("implementation",null),
     OPERATION_INPUTS("inputs",null),
     OPERATION_OUTPUTS("outputs", null),
-    INPUTS("inputs", null);
+    INPUTS("inputs", null),
+
+    GET_PROPERTY("get_property", null),
+    GET_INPUT("get_input", null),
+    GET_OPERATION_OUTPUT("get_operation_output", null);
 
     private String presentation;
     private GraphPropertyEnum storedAs;
index 533008e..915bc22 100644 (file)
@@ -16,9 +16,9 @@ public class OperationInputDefinitionTest {
                // default test
                testSubject = createTestSubject();
                new OperationInputDefinition("", "", true, "");
-               new OperationInputDefinition("stam", testSubject);
+               new OperationInputDefinition("stam", testSubject, null, null);
        }
-       
+
        @Test
        public void testGetLabel() throws Exception {
                OperationInputDefinition testSubject;