summaryrefslogtreecommitdiffstats
path: root/catalog-be/src/main
diff options
context:
space:
mode:
authorojasdubey <ojas.dubey@amdocs.com>2019-01-28 21:47:09 +0530
committerojasdubey <ojas.dubey@amdocs.com>2019-01-29 13:19:58 +0530
commit9c0aa250313380895e9543e7e6fe83b9daf3849e (patch)
treee4a6f852e7585aa8df6b47b83769112cebbaf7a8 /catalog-be/src/main
parentc0693cd275a0d35ab7acefd2ea2a936179041f41 (diff)
Operation Outputs - Operation screen BE
1. Added implementation for using operation outputs as mapping to input from create/update operation screen 2. Handled populating the mapped outputs to Tosca 3. Unit tests Change-Id: I3d4761b07be0d4e363ff84710e92438e694a3b07 Issue-ID: SDC-2085 Signed-off-by: ojasdubey <ojas.dubey@amdocs.com>
Diffstat (limited to 'catalog-be/src/main')
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/InterfaceOperationUtils.java17
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/InterfaceOperationValidation.java370
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/InterfacesOperationsToscaUtil.java49
-rw-r--r--catalog-be/src/main/resources/config/error-configuration.yaml9
4 files changed, 347 insertions, 98 deletions
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/InterfaceOperationUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/InterfaceOperationUtils.java
index 0233711a89..6615e9ef37 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/InterfaceOperationUtils.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/utils/InterfaceOperationUtils.java
@@ -16,10 +16,15 @@
package org.openecomp.sdc.be.components.utils;
+import java.util.List;
import java.util.Map;
import java.util.Optional;
+
+import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
+import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
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;
@@ -61,4 +66,16 @@ public class InterfaceOperationUtils {
.filter(entry -> entry.getValue().getUniqueId().equals(operationId)).findAny();
}
+ public static boolean isOperationInputMappedToComponentProperty(OperationInputDefinition input,
+ List<InputDefinition> inputs) {
+ if (CollectionUtils.isEmpty(inputs)) {
+ return false;
+ }
+ return inputs.stream().anyMatch(inp -> inp.getUniqueId().equals(input.getInputId()))
+ || (input.getInputId().contains(".")
+ && inputs.stream().anyMatch(inp -> inp.getUniqueId().equals(
+ input.getInputId().substring(0, input.getInputId().lastIndexOf('.'))))) ;
+ }
+
+
}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/InterfaceOperationValidation.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/InterfaceOperationValidation.java
index c80f57486d..d17762fc90 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/InterfaceOperationValidation.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/InterfaceOperationValidation.java
@@ -16,7 +16,11 @@
package org.openecomp.sdc.be.components.validation;
+import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.isOperationInputMappedToComponentProperty;
+
+import com.google.common.collect.Sets;
import fj.data.Either;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
@@ -26,13 +30,17 @@ import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
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.dao.api.ActionStatus;
+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.model.InputDefinition;
+import org.openecomp.sdc.be.datatypes.elements.OperationOutputDefinition;
import org.openecomp.sdc.be.model.InterfaceDefinition;
import org.openecomp.sdc.be.model.Operation;
import org.openecomp.sdc.exception.ResponseFormat;
@@ -47,9 +55,10 @@ public class InterfaceOperationValidation {
private static final Logger LOGGER = LoggerFactory.getLogger(InterfaceOperationValidation.class);
- public Either<Boolean, ResponseFormat> validateInterfaceOperations(InterfaceDefinition inputInterfaceDefinition,
- org.openecomp.sdc.be.model.Component component, InterfaceDefinition storedInterfaceDefinition,
- Map<String, InterfaceDefinition> globalInterfaceTypes, boolean isUpdate) {
+ public Either<Boolean, ResponseFormat> validateInterfaceOperations(
+ InterfaceDefinition inputInterfaceDefinition, org.openecomp.sdc.be.model.Component component,
+ InterfaceDefinition storedInterfaceDefinition, Map<String, InterfaceDefinition> globalInterfaceTypes,
+ boolean isUpdate) {
Either<Boolean, ResponseFormat> validateAllowedOperationCountOnLocalInterfaceType =
validateAllowedOperationCountOnLocalInterfaceType(inputInterfaceDefinition, storedInterfaceDefinition,
@@ -71,8 +80,8 @@ public class InterfaceOperationValidation {
}
for (Operation interfaceOperation : inputInterfaceDefinition.getOperationsMap().values()) {
- Either<Boolean, ResponseFormat> interfaceOperationValidatorResponse =
- validateInterfaceOperation(interfaceOperation, storedInterfaceDefinition, component, isUpdate);
+ Either<Boolean, ResponseFormat> interfaceOperationValidatorResponse = validateInterfaceOperation(
+ interfaceOperation, storedInterfaceDefinition, inputInterfaceDefinition, component, isUpdate);
if (interfaceOperationValidatorResponse.isRight()) {
return interfaceOperationValidatorResponse;
}
@@ -87,15 +96,13 @@ public class InterfaceOperationValidation {
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 && (inputInterfaceDefinition.getOperations().size() > 1
+ || (!isUpdate && storedInterfaceDefinition != null
+ && storedInterfaceDefinition.getType().equalsIgnoreCase(inputInterfaceDefinition.getType())))) {
return Either.right(getResponseFormatManager()
- .getResponseFormat(ActionStatus.INTERFACE_OPERATION_INVALID_FOR_LOCAL_TYPE,
- inputInterfaceDefinition.getType()));
+ .getResponseFormat(ActionStatus.INTERFACE_OPERATION_INVALID_FOR_LOCAL_TYPE,
+ inputInterfaceDefinition.getType()));
}
return Either.left(Boolean.TRUE);
@@ -105,22 +112,17 @@ public class InterfaceOperationValidation {
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)));
+ 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()));
+ .getResponseFormat(ActionStatus.INTERFACE_OPERATION_INVALID_FOR_GLOBAL_TYPE,
+ interfaceDefinition.getType()));
}
}
return Either.left(Boolean.TRUE);
@@ -140,16 +142,19 @@ public class InterfaceOperationValidation {
}
private Either<Boolean, ResponseFormat> validateInterfaceOperation(Operation interfaceOperation,
- InterfaceDefinition interfaceDefinition, org.openecomp.sdc.be.model.Component component, boolean isUpdate) {
+ InterfaceDefinition storedInterfaceDefinition, InterfaceDefinition inputInterfaceDefinition,
+ org.openecomp.sdc.be.model.Component component, boolean isUpdate) {
ResponseFormatManager responseFormatManager = getResponseFormatManager();
Either<Boolean, ResponseFormat> interfaceOperationTypeResponse =
- isInterfaceOperationTypeValid(interfaceOperation, responseFormatManager, interfaceDefinition, isUpdate);
+ isInterfaceOperationTypeValid(interfaceOperation, responseFormatManager, storedInterfaceDefinition,
+ isUpdate);
if (interfaceOperationTypeResponse.isRight()) {
return Either.right(interfaceOperationTypeResponse.right().value());
}
- if (null != interfaceOperation.getInputs()) {
+ if (null != interfaceOperation.getInputs()
+ && CollectionUtils.isNotEmpty(interfaceOperation.getInputs().getListToscaDataDefinition())) {
Either<Boolean, ResponseFormat> inputParametersResponse =
validateInputParameters(interfaceOperation, responseFormatManager);
if (inputParametersResponse.isRight()) {
@@ -157,14 +162,15 @@ public class InterfaceOperationValidation {
}
Either<Boolean, ResponseFormat> inputPropertyExistInComponent =
- validateInputPropertyExistInComponent(interfaceOperation, component, responseFormatManager);
+ validateInputPropertyExistInComponent(interfaceOperation,
+ inputInterfaceDefinition, component, responseFormatManager);
if (inputPropertyExistInComponent.isRight()) {
return Either.right(inputPropertyExistInComponent.right().value());
-
}
}
- if (null != interfaceOperation.getOutputs()) {
+ if (null != interfaceOperation.getOutputs()
+ && CollectionUtils.isNotEmpty(interfaceOperation.getOutputs().getListToscaDataDefinition())) {
Either<Boolean, ResponseFormat> outputParametersResponse =
validateOutputParameters(interfaceOperation, responseFormatManager);
if (outputParametersResponse.isRight()) {
@@ -172,15 +178,81 @@ public class InterfaceOperationValidation {
}
}
+ if (MapUtils.isNotEmpty(component.getInterfaces()) && isUpdate) {
+ Either<Boolean, ResponseFormat> mappedOutputDeletedResponse =
+ validateMappedOutputNotDeleted(interfaceOperation, component, inputInterfaceDefinition,
+ responseFormatManager);
+ if (mappedOutputDeletedResponse.isRight()) {
+ return Either.right(mappedOutputDeletedResponse.right().value());
+ }
+ }
+
return Either.left(Boolean.TRUE);
}
+
+ private Either<Boolean, ResponseFormat> validateMappedOutputNotDeleted(Operation interfaceOperation,
+ org.openecomp.sdc.be.model.Component component, InterfaceDefinition interfaceDefinition,
+ ResponseFormatManager responseFormatManager) {
+
+ List<OperationOutputDefinition> existingOperationOutputs =
+ getInterfaceOperationOutputs(interfaceOperation.getUniqueId(), component.getInterfaces());
+ if (existingOperationOutputs.isEmpty()) {
+ return Either.left(Boolean.TRUE);
+ }
+ Set<String> existingOperationOutputNames = existingOperationOutputs.stream()
+ .map(OperationOutputDefinition::getName)
+ .collect(Collectors.toSet());
+
+ ListDataDefinition<OperationOutputDefinition> currentOutputs = interfaceOperation.getOutputs();
+ Set<String> currentOperationOutputNames = new HashSet<>();
+ if (currentOutputs != null && !currentOutputs.isEmpty()) {
+ currentOperationOutputNames = currentOutputs.getListToscaDataDefinition().stream()
+ .map(OperationOutputDefinition::getName)
+ .collect(Collectors.toSet());
+ }
+ String mappedOutputPrefix = interfaceDefinition.getType() + "." + interfaceOperation.getName();
+ 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());
+
+ if (CollectionUtils.isNotEmpty(deletedMappedOutputs)) {
+ return getMappedOutputErrorResponse(responseFormatManager, deletedMappedOutputs);
+ }
+ return Either.left(Boolean.TRUE);
+ }
+
+ private boolean isMappedOutputDeleted(String mappedOutputPrefix, String outputName,
+ Map<String, InterfaceDefinition> componentInterfaces) {
+ List<OperationInputDefinition> interfaceOperationInputs =
+ getOtherOperationInputsOfComponent(mappedOutputPrefix, componentInterfaces);
+ return interfaceOperationInputs.stream()
+ .anyMatch(operationInputDefinition -> operationInputDefinition.getInputId()
+ .equals(mappedOutputPrefix + "." + outputName));
+ }
+
+ private Either<Boolean, ResponseFormat> getMappedOutputErrorResponse(ResponseFormatManager responseFormatManager,
+ Set<String> deletedMappedOutputs) {
+ String deletedOutputNameList = String.join(",", deletedMappedOutputs);
+ LOGGER.error("Cannot update name or delete interface operation output(s) '{}' mapped to an operation input",
+ deletedOutputNameList);
+ ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus
+ .INTERFACE_OPERATION_MAPPED_OUTPUT_DELETED, deletedOutputNameList);
+ return Either.right(errorResponse);
+ }
+
+
protected ResponseFormatManager getResponseFormatManager() {
return ResponseFormatManager.getInstance();
}
private Either<Boolean, ResponseFormat> isInterfaceOperationTypeValid(Operation interfaceOperation,
- ResponseFormatManager responseFormatManager, InterfaceDefinition interfaceDefinition, boolean isUpdate) {
+ ResponseFormatManager responseFormatManager,
+ InterfaceDefinition interfaceDefinition,
+ boolean isUpdate) {
Either<Boolean, ResponseFormat> operationTypeEmptyEither =
isOperationTypeEmpty(responseFormatManager, interfaceOperation.getName());
@@ -194,8 +266,8 @@ public class InterfaceOperationValidation {
return Either.right(operationTypeRegexValidationResponse.right().value());
}
- Either<Boolean, ResponseFormat> operationTypeUniqueResponse =
- validateOperationTypeUnique(interfaceOperation, interfaceDefinition, isUpdate);
+ Either<Boolean, ResponseFormat> operationTypeUniqueResponse = validateOperationTypeUnique(interfaceOperation,
+ interfaceDefinition, isUpdate);
if (operationTypeUniqueResponse.isRight()) {
return Either.right(operationTypeUniqueResponse.right().value());
}
@@ -209,7 +281,7 @@ public class InterfaceOperationValidation {
}
private Either<Boolean, ResponseFormat> validateInputParameters(Operation interfaceOperation,
- ResponseFormatManager responseFormatManager) {
+ ResponseFormatManager responseFormatManager) {
if (isInputParameterNameEmpty(interfaceOperation)) {
LOGGER.error("Interface operation input parameter name can't be empty");
ResponseFormat inputResponse =
@@ -222,38 +294,16 @@ public class InterfaceOperationValidation {
if (validateInputParametersUniqueResponse.isRight()) {
LOGGER.error("Interface operation input parameter names {} already in use",
validateInputParametersUniqueResponse.right().value());
- ResponseFormat inputResponse = responseFormatManager.getResponseFormat(
- ActionStatus.INTERFACE_OPERATION_INPUT_NAME_ALREADY_IN_USE,
- validateInputParametersUniqueResponse.right().value().toString());
+ ResponseFormat inputResponse =
+ responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_INPUT_NAME_ALREADY_IN_USE,
+ validateInputParametersUniqueResponse.right().value().toString());
return Either.right(inputResponse);
}
return Either.left(Boolean.TRUE);
}
- private Either<Boolean, ResponseFormat> validateInputPropertyExistInComponent(Operation operation,
- org.openecomp.sdc.be.model.Component component, ResponseFormatManager responseFormatManager) {
-
- List<OperationInputDefinition> inputListToscaDataDefinition =
- operation.getInputs().getListToscaDataDefinition();
- for (OperationInputDefinition inputDefinition : inputListToscaDataDefinition) {
- if (!validateInputExistsInComponent(inputDefinition, component.getInputs())) {
- String missingPropertyName = inputDefinition.getInputId().contains(".")
- ? inputDefinition.getInputId().substring(
- inputDefinition.getInputId().indexOf('.') + 1)
- : inputDefinition.getInputId();
- LOGGER.error("Interface operation input property {} not found in component input properties",
- missingPropertyName);
- ResponseFormat inputResponse = responseFormatManager.getResponseFormat(
- ActionStatus.INTERFACE_OPERATION_INPUT_PROPERTY_NOT_FOUND_IN_COMPONENT, missingPropertyName,
- component.getComponentType().getValue());
- return Either.right(inputResponse);
- }
- }
- return Either.left(Boolean.TRUE);
- }
-
private Either<Boolean, ResponseFormat> validateOutputParameters(Operation interfaceOperation,
- ResponseFormatManager responseFormatManager) {
+ ResponseFormatManager responseFormatManager) {
if (isOutputParameterNameEmpty(interfaceOperation)) {
LOGGER.error("Interface operation output parameter name can't be empty");
ResponseFormat inputResponse =
@@ -266,9 +316,9 @@ public class InterfaceOperationValidation {
if (validateOutputParametersUniqueResponse.isRight()) {
LOGGER.error("Interface operation output parameter names {} already in use",
validateOutputParametersUniqueResponse.right().value());
- ResponseFormat inputResponse = responseFormatManager.getResponseFormat(
- ActionStatus.INTERFACE_OPERATION_OUTPUT_NAME_ALREADY_IN_USE,
- validateOutputParametersUniqueResponse.right().value().toString());
+ ResponseFormat inputResponse =
+ responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_OUTPUT_NAME_ALREADY_IN_USE,
+ validateOutputParametersUniqueResponse.right().value().toString());
return Either.right(inputResponse);
}
return Either.left(Boolean.TRUE);
@@ -330,31 +380,22 @@ public class InterfaceOperationValidation {
inputParam -> inputParam.getName() == null || inputParam.getName().trim().equals(StringUtils.EMPTY));
}
+
private Either<Boolean, Set<String>> isInputParametersUnique(Operation operationDataDefinition) {
Set<String> inputParamNamesSet = new HashSet<>();
Set<String> duplicateParamNamesToReturn = new HashSet<>();
- operationDataDefinition.getInputs().getListToscaDataDefinition().forEach(inputParam -> {
- if (!inputParamNamesSet.add(inputParam.getName().trim())) {
- duplicateParamNamesToReturn.add(inputParam.getName().trim());
- }
- });
+ operationDataDefinition.getInputs().getListToscaDataDefinition()
+ .forEach(inputParam -> {
+ if (!inputParamNamesSet.add(inputParam.getName().trim())) {
+ duplicateParamNamesToReturn.add(inputParam.getName().trim());
+ }
+ });
if (!duplicateParamNamesToReturn.isEmpty()) {
return Either.right(duplicateParamNamesToReturn);
}
return Either.left(Boolean.TRUE);
}
- private boolean validateInputExistsInComponent(OperationInputDefinition input, List<InputDefinition> inputs) {
- return inputs.stream().anyMatch(inp -> inp.getUniqueId().equals(input.getInputId()))
- || (input.getInputId().contains(".")
- && inputs.stream()
- .anyMatch(inp -> inp.getUniqueId()
- .equals(input.getInputId()
- .substring(0,
- input.getInputId()
- .lastIndexOf('.')))));
- }
-
private Boolean isOutputParameterNameEmpty(Operation operationDataDefinition) {
return operationDataDefinition.getOutputs().getListToscaDataDefinition().stream().anyMatch(
outputParam -> outputParam.getName() == null || outputParam.getName().trim().equals(StringUtils.EMPTY));
@@ -363,17 +404,170 @@ public class InterfaceOperationValidation {
private Either<Boolean, Set<String>> isOutputParametersUnique(Operation operationDataDefinition) {
Set<String> outputParamNamesSet = new HashSet<>();
Set<String> duplicateParamNamesToReturn = new HashSet<>();
- operationDataDefinition.getOutputs().getListToscaDataDefinition().forEach(outputParam -> {
- if (!outputParamNamesSet.add(outputParam.getName().trim())) {
- duplicateParamNamesToReturn.add(outputParam.getName().trim());
- }
- });
+ operationDataDefinition.getOutputs().getListToscaDataDefinition()
+ .forEach(outputParam -> {
+ if (!outputParamNamesSet.add(outputParam.getName().trim())) {
+ duplicateParamNamesToReturn.add(outputParam.getName().trim());
+ }
+ });
if (!duplicateParamNamesToReturn.isEmpty()) {
return Either.right(duplicateParamNamesToReturn);
}
return Either.left(Boolean.TRUE);
}
+ private Either<Boolean, ResponseFormat> validateInputPropertyExistInComponent(Operation operation,
+ InterfaceDefinition inputInterfaceDefinition, org.openecomp.sdc.be.model.Component component,
+ ResponseFormatManager responseFormatManager) {
+
+ boolean isOperationInputToInputPropertyMappingValid = false;
+ boolean isOperationInputToOtherOperationOutputMappingValid = false;
+ String mappingName = "";
+ List<OperationInputDefinition> inputListToscaDataDefinition =
+ operation.getInputs().getListToscaDataDefinition();
+ for (OperationInputDefinition inputDefinition : inputListToscaDataDefinition) {
+ if (isOperationInputMappedToComponentProperty(inputDefinition, component.getInputs())) {
+ isOperationInputToInputPropertyMappingValid = true;
+ } else {
+ mappingName = inputDefinition.getInputId().contains(".")
+ ? inputDefinition.getInputId().substring(inputDefinition.getInputId().lastIndexOf(".") + 1)
+ : inputDefinition.getInputId();
+ break;
+ }
+ }
+ if (isOperationInputToInputPropertyMappingValid) {
+ return Either.left(Boolean.TRUE);
+ }
+
+ //Mapped property not found in the component properties.. Check in other operation output parameters of
+ // component (other operation => not having the same full name)
+ ListDataDefinition<OperationOutputDefinition> outputListDataDefinition =
+ getOtherOperationOutputsOfComponent(inputInterfaceDefinition.getType(), operation.getName(), component);
+
+ List<OperationOutputDefinition> componentOutputsFromOtherOperations =
+ outputListDataDefinition.getListToscaDataDefinition();
+ if (validateOutputExistsInComponent(mappingName, componentOutputsFromOtherOperations)) {
+ isOperationInputToOtherOperationOutputMappingValid = true;
+ } else {
+ //Get the output parameter display name from the full name
+ mappingName = getOperationOutputName(mappingName);
+ }
+
+ if (!isOperationInputToOtherOperationOutputMappingValid) {
+ LOGGER.error("Interface operation input parameter property {} not found in component input properties or"
+ + " outputs of other operations.", mappingName);
+ ResponseFormat inputResponse = responseFormatManager
+ .getResponseFormat(ActionStatus.INTERFACE_OPERATION_INPUT_PROPERTY_NOT_FOUND_IN_COMPONENT,
+ mappingName, component.getComponentType().getValue());
+ return Either.right(inputResponse);
+ }
+ return Either.left(Boolean.TRUE);
+ }
+
+ private boolean validateOutputExistsInComponent(String mappedOutputName,
+ List<OperationOutputDefinition> outputs) {
+ return outputs.stream()
+ .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)
+ * @param componentInterfaces Interfaces of the component
+ */
+ private List<OperationInputDefinition> getOtherOperationInputsOfComponent(String currentOperationIdentifier,
+ Map<String, InterfaceDefinition>
+ componentInterfaces) {
+ List<OperationInputDefinition> otherOperationInputs = new ArrayList<>();
+ if (MapUtils.isEmpty(componentInterfaces)) {
+ return otherOperationInputs;
+ }
+ for (Map.Entry<String, InterfaceDefinition> interfaceDefinitionEntry : componentInterfaces.entrySet()) {
+ final Map<String, OperationDataDefinition> operations = interfaceDefinitionEntry.getValue().getOperations();
+ if (MapUtils.isEmpty(operations)) {
+ continue;
+ }
+ for (Map.Entry<String, OperationDataDefinition> operationEntry : operations.entrySet()) {
+ ListDataDefinition<OperationInputDefinition> inputs = operationEntry.getValue().getInputs();
+ String expectedOperationIdentifier =
+ interfaceDefinitionEntry.getValue().getType() + "." + operationEntry.getValue().getName();
+ if (!currentOperationIdentifier.equals(expectedOperationIdentifier) && !inputs.isEmpty()) {
+ otherOperationInputs.addAll(inputs.getListToscaDataDefinition());
+ }
+ }
+ }
+ 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
+ * @param componentInterfaces Interfaces of the component
+ */
+ private List<OperationOutputDefinition> getInterfaceOperationOutputs(String inputOperationId,
+ Map<String, InterfaceDefinition>
+ componentInterfaces) {
+ List<OperationOutputDefinition> operationOutputDefinitions = new ArrayList<>();
+ if (MapUtils.isEmpty(componentInterfaces)) {
+ return operationOutputDefinitions;
+ }
+ for (Map.Entry<String, InterfaceDefinition> interfaceDefinitionEntry : componentInterfaces.entrySet()) {
+ final Map<String, OperationDataDefinition> operations = interfaceDefinitionEntry.getValue().getOperations();
+ if (MapUtils.isEmpty(operations)) {
+ continue;
+ }
+ for (Map.Entry<String, OperationDataDefinition> operationEntry : operations.entrySet()) {
+ String expectedOperationId = operationEntry.getValue().getUniqueId();
+ if (expectedOperationId.equals(inputOperationId)) {
+ ListDataDefinition<OperationOutputDefinition> operationOutputs =
+ operationEntry.getValue().getOutputs();
+ return (Objects.isNull(operationOutputs) || operationOutputs.isEmpty())
+ ? operationOutputDefinitions
+ : operationOutputs.getListToscaDataDefinition();
+ }
+ }
+ }
+ return operationOutputDefinitions;
+ }
+
private boolean isValidOperationType(String operationType) {
return Pattern.matches(TYPE_VALIDATION_REGEX, operationType);
}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/InterfacesOperationsToscaUtil.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/InterfacesOperationsToscaUtil.java
index fbef11d2e8..efed3e9f15 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/InterfacesOperationsToscaUtil.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/InterfacesOperationsToscaUtil.java
@@ -16,6 +16,8 @@
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;
@@ -47,10 +49,12 @@ public class InterfacesOperationsToscaUtil {
private static final String DEFAULT = "default";
private static final String DEFAULT_HAS_UNDERSCORE = "_default";
private static final String DOT = ".";
- private static final String SELF = "SELF";
- private static final String GET_PROPERTY = "get_property";
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";
+
private InterfacesOperationsToscaUtil() {
}
@@ -127,7 +131,7 @@ public class InterfacesOperationsToscaUtil {
toscaOperation.setImplementation(operationArtifactPath);
}
toscaOperation.setDescription(operationEntry.getValue().getDescription());
- fillToscaOperationInputs(operationEntry.getValue(), toscaOperation);
+ fillToscaOperationInputs(operationEntry.getValue(), toscaOperation, interfaceType, component);
toscaOperations.put(operationEntry.getValue().getName(), toscaOperation);
}
@@ -176,7 +180,9 @@ public class InterfacesOperationsToscaUtil {
}
private static void fillToscaOperationInputs(OperationDataDefinition operation,
- ToscaLifecycleOperationDefinition toscaOperation) {
+ ToscaLifecycleOperationDefinition toscaOperation,
+ String interfaceType,
+ Component component) {
if (Objects.isNull(operation.getInputs()) || operation.getInputs().isEmpty()) {
toscaOperation.setInputs(null);
return;
@@ -186,12 +192,16 @@ public class InterfacesOperationsToscaUtil {
for (OperationInputDefinition input : operation.getInputs().getListToscaDataDefinition()) {
ToscaProperty toscaInput = new ToscaProperty();
toscaInput.setDescription(input.getDescription());
- String mappedPropertyName = null;
+ String mappedPropertyName;
if (Objects.nonNull(input.getInputId())) {
- mappedPropertyName = input.getInputId().substring(input.getInputId().indexOf(DOT) + 1);
+ 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, interfaceType));
+ }
}
- toscaInput.setDefaultp(createDefaultValue(mappedPropertyName));
-
toscaInput.setType(input.getType());
toscaInput.setRequired(input.isRequired());
toscaInputs.put(input.getName(), toscaInput);
@@ -200,7 +210,7 @@ public class InterfacesOperationsToscaUtil {
toscaOperation.setInputs(toscaInputs);
}
- private static Map<String, List<String>> createDefaultValue(String propertyName) {
+ private static Map<String, List<String>> createMappedInputPropertyDefaultValue(String propertyName) {
Map<String, List<String>> getPropertyMap = new HashMap<>();
List<String> values = new ArrayList<>();
values.add(SELF);
@@ -213,6 +223,27 @@ public class InterfacesOperationsToscaUtil {
return getPropertyMap;
}
+ /**
+ * Create the value for operation input mapped to an operation output
+ * @param propertyName the mapped other operation output full name
+ * @param interfaceType full interface name
+ * @return input map for tosca
+ */
+ private static Map<String, List<String>> createMappedOutputDefaultValue(String propertyName, String interfaceType) {
+ 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>
+ List<String> defaultMappedOperationOutputValue = new ArrayList<>();
+ defaultMappedOperationOutputValue.add(SELF);
+ String fullOutputPropertyName =
+ propertyName.substring(propertyName.indexOf(interfaceType) + interfaceType.length() + 1);
+ defaultMappedOperationOutputValue.add(interfaceType);
+ //Output name should not contain dot
+ defaultMappedOperationOutputValue.addAll(Arrays.asList(fullOutputPropertyName.split("\\.")));
+ getOperationOutputMap.put(GET_OPERATION_OUTPUT, defaultMappedOperationOutputValue);
+ return getOperationOutputMap;
+ }
+
private static Map<String, Object> getObjectAsMap(Object obj) {
ObjectMapper objectMapper = new ObjectMapper();
if (obj instanceof ToscaInterfaceDefinition) {
diff --git a/catalog-be/src/main/resources/config/error-configuration.yaml b/catalog-be/src/main/resources/config/error-configuration.yaml
index ff86aff820..315027b43e 100644
--- a/catalog-be/src/main/resources/config/error-configuration.yaml
+++ b/catalog-be/src/main/resources/config/error-configuration.yaml
@@ -2137,7 +2137,7 @@ errors:
# %1 - Interface Operation input property name, component type
INTERFACE_OPERATION_INPUT_PROPERTY_NOT_FOUND_IN_COMPONENT: {
code: 404,
- message: "Error: Interface operation input parameter property '%1' not found in '%2' input properties.",
+ message: "Error: Interface operation input parameter property '%1' not found in '%2' input properties or outputs of other operations.",
messageId: "SVC4708"
}
#---------SVC4709-----------------------------
@@ -2172,4 +2172,11 @@ errors:
code: 400,
message: "Error: Invalid input, only pre-defined operation names are allowed in global interface type '%1'",
messageId: "SVC4713"
+ }
+#---------SVC4714-----------------------------
+# %1 - Interface Operation output name
+ INTERFACE_OPERATION_MAPPED_OUTPUT_DELETED: {
+ code: 400,
+ message: "Error: Cannot update name or delete interface operation output(s) '%1' mapped to an operation input",
+ messageId: "SVC4714"
} \ No newline at end of file