2 * Copyright © 2016-2018 European Support Limited
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.openecomp.sdc.be.components.validation;
18 import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.getOperationOutputName;
19 import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.getOtherOperationOutputsOfComponent;
20 import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.isOperationInputMappedToComponentInput;
21 import static org.openecomp.sdc.be.components.utils.PropertiesUtils.isCapabilityProperty;
23 import com.google.common.collect.Sets;
24 import fj.data.Either;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.List;
31 import java.util.Objects;
32 import java.util.Optional;
34 import java.util.regex.Pattern;
35 import java.util.stream.Collectors;
36 import java.util.stream.Stream;
37 import org.apache.commons.collections.CollectionUtils;
38 import org.apache.commons.collections.MapUtils;
39 import org.apache.commons.lang3.StringUtils;
40 import org.openecomp.sdc.be.components.impl.ResponseFormatManager;
41 import org.openecomp.sdc.be.components.utils.InterfaceOperationUtils;
42 import org.openecomp.sdc.be.dao.api.ActionStatus;
43 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
44 import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
45 import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
46 import org.openecomp.sdc.be.datatypes.elements.OperationOutputDefinition;
47 import org.openecomp.sdc.be.model.InterfaceDefinition;
48 import org.openecomp.sdc.be.model.Operation;
49 import org.openecomp.sdc.exception.ResponseFormat;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52 import org.springframework.stereotype.Component;
54 @Component("interfaceOperationValidation")
55 public class InterfaceOperationValidation {
57 private static final String TYPE_VALIDATION_REGEX = "^[a-zA-Z0-9_]{1,200}$";
58 private static final Logger LOGGER = LoggerFactory.getLogger(InterfaceOperationValidation.class);
60 public Either<Boolean, ResponseFormat> validateInterfaceOperations(InterfaceDefinition inputInterfaceDefinition,
61 org.openecomp.sdc.be.model.Component component,
62 InterfaceDefinition storedInterfaceDefinition,
63 Map<String, InterfaceDefinition> globalInterfaceTypes, boolean isUpdate) {
64 Either<Boolean, ResponseFormat> validateAllowedOperationsOnGlobalInterfaceType = validateAllowedOperationsOnGlobalInterfaceType(
65 inputInterfaceDefinition, globalInterfaceTypes);
66 if (validateAllowedOperationsOnGlobalInterfaceType.isRight()) {
67 return validateAllowedOperationsOnGlobalInterfaceType;
69 Either<Boolean, ResponseFormat> validateOperationNameUniqueness = validateOperationNameUniquenessInCollection(
70 inputInterfaceDefinition.getOperationsMap().values());
71 if (validateOperationNameUniqueness.isRight()) {
72 return validateOperationNameUniqueness;
74 for (Operation interfaceOperation : inputInterfaceDefinition.getOperationsMap().values()) {
75 Either<Boolean, ResponseFormat> interfaceOperationValidatorResponse = validateInterfaceOperation(interfaceOperation,
76 storedInterfaceDefinition, inputInterfaceDefinition, component, isUpdate);
77 if (interfaceOperationValidatorResponse.isRight()) {
78 return interfaceOperationValidatorResponse;
81 return Either.left(Boolean.TRUE);
84 public Either<Boolean, ResponseFormat> validateDeleteOperationContainsNoMappedOutput(Operation interfaceOperationToDelete,
85 org.openecomp.sdc.be.model.Component component,
86 InterfaceDefinition storedInterfaceDefinition) {
87 ResponseFormatManager responseFormatManager = getResponseFormatManager();
88 List<OperationOutputDefinition> existingOperationOutputs = getInterfaceOperationOutputs(interfaceOperationToDelete.getUniqueId(),
89 component.getInterfaces());
90 if (existingOperationOutputs.isEmpty()) {
91 return Either.left(Boolean.TRUE);
93 String mappedOutputPrefix = storedInterfaceDefinition.getType() + "." + interfaceOperationToDelete.getName();
94 List<OperationInputDefinition> interfaceOperationInputs = getOtherOperationInputsOfComponent(mappedOutputPrefix, component.getInterfaces());
95 Set<String> mappedOutputsInDeletedOperation = new HashSet<>();
96 Set<String> existingOperationOutputNames = existingOperationOutputs.stream().map(OperationOutputDefinition::getName)
97 .collect(Collectors.toSet());
98 for (String existingOperationOutputName : existingOperationOutputNames) {
99 Set<String> matchedOutputsMappedToInputs = interfaceOperationInputs.stream().filter(
100 operationInputDefinition -> operationInputDefinition.getInputId().equals(mappedOutputPrefix + "." + existingOperationOutputName))
101 .map(operationInputDefinition -> getOperationOutputName(operationInputDefinition.getInputId())).collect(Collectors.toSet());
102 mappedOutputsInDeletedOperation.addAll(matchedOutputsMappedToInputs);
104 if (CollectionUtils.isNotEmpty(mappedOutputsInDeletedOperation)) {
105 return getMappedOutputErrorResponse(responseFormatManager, mappedOutputsInDeletedOperation,
106 "Cannot delete interface operation with output(s) '{}' mapped to another operation input",
107 ActionStatus.INTERFACE_OPERATION_DELETE_WITH_MAPPED_OUTPUT);
109 return Either.left(Boolean.TRUE);
112 private Either<Boolean, ResponseFormat> validateAllowedOperationsOnGlobalInterfaceType(InterfaceDefinition interfaceDefinition,
113 Map<String, InterfaceDefinition> globalInterfaceTypes) {
114 if (globalInterfaceTypes == null) {
115 return Either.left(Boolean.TRUE);
117 boolean isOperationValidOnGlobalInterfaceType = Stream.of(interfaceDefinition).filter(interfaceDef -> globalInterfaceTypes.values().stream()
118 .anyMatch(interfaceDef1 -> interfaceDef1.getType().equalsIgnoreCase(interfaceDef.getType())))
119 .flatMap(interfaceDef -> interfaceDef.getOperationsMap().values().stream().map(Operation::getName)).allMatch(
120 operationName -> globalInterfaceTypes.values().stream().flatMap(interfaceDef -> interfaceDef.getOperationsMap().keySet().stream())
121 .anyMatch(opName -> opName.equalsIgnoreCase(operationName)));
122 if (!isOperationValidOnGlobalInterfaceType) {
123 return Either.right(getResponseFormatManager()
124 .getResponseFormat(ActionStatus.INTERFACE_OPERATION_INVALID_FOR_GLOBAL_TYPE, interfaceDefinition.getType()));
126 return Either.left(Boolean.TRUE);
129 private Either<Boolean, ResponseFormat> validateOperationNameUniquenessInCollection(Collection<Operation> operationList) {
130 HashSet<String> operationNames = new HashSet<>();
131 for (Operation operation : operationList) {
132 if (!operationNames.add(operation.getName())) {
134 .right(getResponseFormatManager().getResponseFormat(ActionStatus.INTERFACE_OPERATION_NAME_ALREADY_IN_USE, operation.getName()));
137 return Either.left(Boolean.TRUE);
140 private Either<Boolean, ResponseFormat> validateInterfaceOperation(Operation interfaceOperation, InterfaceDefinition storedInterfaceDefinition,
141 InterfaceDefinition inputInterfaceDefinition,
142 org.openecomp.sdc.be.model.Component component, boolean isUpdate) {
143 ResponseFormatManager responseFormatManager = getResponseFormatManager();
144 Either<Boolean, ResponseFormat> interfaceOperationTypeResponse = isInterfaceOperationTypeValid(interfaceOperation, responseFormatManager,
145 storedInterfaceDefinition, isUpdate);
146 if (interfaceOperationTypeResponse.isRight()) {
147 return Either.right(interfaceOperationTypeResponse.right().value());
149 if (null != interfaceOperation.getInputs() && CollectionUtils.isNotEmpty(interfaceOperation.getInputs().getListToscaDataDefinition())) {
150 Either<Boolean, ResponseFormat> inputParametersResponse = validateInputParameters(interfaceOperation, responseFormatManager);
151 if (inputParametersResponse.isRight()) {
152 return Either.right(inputParametersResponse.right().value());
154 Either<Boolean, ResponseFormat> inputPropertyExistInComponent = validateInputPropertyExistInComponent(interfaceOperation,
155 inputInterfaceDefinition, component, responseFormatManager);
156 if (inputPropertyExistInComponent.isRight()) {
157 return Either.right(inputPropertyExistInComponent.right().value());
160 if (null != interfaceOperation.getOutputs() && CollectionUtils.isNotEmpty(interfaceOperation.getOutputs().getListToscaDataDefinition())) {
161 Either<Boolean, ResponseFormat> outputParametersResponse = validateOutputParameters(interfaceOperation, responseFormatManager);
162 if (outputParametersResponse.isRight()) {
163 return Either.right(outputParametersResponse.right().value());
166 if (MapUtils.isNotEmpty(component.getInterfaces()) && isUpdate) {
167 Either<Boolean, ResponseFormat> mappedOutputModifiedResponse = validateMappedOutputNotModified(interfaceOperation, component,
168 inputInterfaceDefinition, responseFormatManager);
169 if (mappedOutputModifiedResponse.isRight()) {
170 return Either.right(mappedOutputModifiedResponse.right().value());
173 return Either.left(Boolean.TRUE);
176 private Either<Boolean, ResponseFormat> validateMappedOutputNotModified(Operation interfaceOperation,
177 org.openecomp.sdc.be.model.Component component,
178 InterfaceDefinition interfaceDefinition,
179 ResponseFormatManager responseFormatManager) {
180 List<OperationOutputDefinition> existingOperationOutputs = getInterfaceOperationOutputs(interfaceOperation.getUniqueId(),
181 component.getInterfaces());
182 if (existingOperationOutputs.isEmpty()) {
183 return Either.left(Boolean.TRUE);
185 Set<String> existingOperationOutputNames = existingOperationOutputs.stream().map(OperationOutputDefinition::getName)
186 .collect(Collectors.toSet());
187 ListDataDefinition<OperationOutputDefinition> currentOutputs = interfaceOperation.getOutputs();
188 Set<String> currentOperationOutputNames = new HashSet<>();
189 if (currentOutputs != null && !currentOutputs.isEmpty()) {
190 currentOperationOutputNames = currentOutputs.getListToscaDataDefinition().stream().map(OperationOutputDefinition::getName)
191 .collect(Collectors.toSet());
193 String mappedOutputPrefix = interfaceDefinition.getType() + "." + interfaceOperation.getName();
194 //Get the deleted outputs (name changed also equivalent to deleted)
195 Set<String> deletedOutputs = Sets.difference(existingOperationOutputNames, currentOperationOutputNames);
196 Set<String> deletedMappedOutputs = getModifiedMappedOutputs(deletedOutputs, mappedOutputPrefix, component.getInterfaces());
197 if (CollectionUtils.isNotEmpty(deletedMappedOutputs)) {
198 return getMappedOutputErrorResponse(responseFormatManager, deletedMappedOutputs,
199 "Cannot update or delete interface operation output(s) '{}' mapped to an operation input",
200 ActionStatus.INTERFACE_OPERATION_MAPPED_OUTPUT_MODIFIED);
202 if (currentOutputs != null && !currentOutputs.isEmpty()) {
203 //Get the unchanged outputs based on name to see if other attributes (type/mandatory) have not been changed
204 Set<String> unchangedOutputNames = Sets.intersection(existingOperationOutputNames, currentOperationOutputNames);
205 Set<String> modifiedOutputNames = getModifiedOutputNames(currentOutputs.getListToscaDataDefinition(), existingOperationOutputs,
206 unchangedOutputNames);
207 Set<String> modifiedMappedOutputNames = getModifiedMappedOutputs(modifiedOutputNames, mappedOutputPrefix, component.getInterfaces());
208 if (CollectionUtils.isNotEmpty(modifiedMappedOutputNames)) {
209 return getMappedOutputErrorResponse(responseFormatManager, modifiedMappedOutputNames,
210 "Cannot update or delete interface operation output(s) '{}' mapped to an operation input",
211 ActionStatus.INTERFACE_OPERATION_MAPPED_OUTPUT_MODIFIED);
214 return Either.left(Boolean.TRUE);
217 private Set<String> getModifiedMappedOutputs(Set<String> modifiedOutputNames, String mappedOutputPrefix,
218 Map<String, InterfaceDefinition> componentInterfaces) {
219 return modifiedOutputNames.stream()
220 .filter(modifiedOutputName -> isMappedOutputModified(mappedOutputPrefix, modifiedOutputName, componentInterfaces))
221 .map(InterfaceOperationUtils::getOperationOutputName).collect(Collectors.toSet());
224 private boolean isMappedOutputModified(String mappedOutputPrefix, String outputName, Map<String, InterfaceDefinition> componentInterfaces) {
225 List<OperationInputDefinition> interfaceOperationInputs = getOtherOperationInputsOfComponent(mappedOutputPrefix, componentInterfaces);
226 return interfaceOperationInputs.stream()
227 .anyMatch(operationInputDefinition -> operationInputDefinition.getInputId().equals(mappedOutputPrefix + "." + outputName));
230 private static Set<String> getModifiedOutputNames(List<OperationOutputDefinition> currentOperationOutputs,
231 List<OperationOutputDefinition> existingOperationOutputs, Set<String> unchangedOutputNames) {
232 Set<String> modifiedOutputDefinitionNames = new HashSet<>();
233 Map<String, OperationOutputDefinition> newOutputMap = currentOperationOutputs.stream().collect(
234 Collectors.toMap(OperationOutputDefinition::getName, (OperationOutputDefinition operationOutputDefinition) -> operationOutputDefinition));
235 Map<String, OperationOutputDefinition> existingOutputMap = existingOperationOutputs.stream().collect(
236 Collectors.toMap(OperationOutputDefinition::getName, (OperationOutputDefinition operationOutputDefinition) -> operationOutputDefinition));
237 for (String outputName : unchangedOutputNames) {
238 OperationOutputDefinition existingOutputDefinition = existingOutputMap.get(outputName);
239 OperationOutputDefinition newOutputDefinition = newOutputMap.get(outputName);
240 if (!existingOutputDefinition.getType().equals(newOutputDefinition.getType()) || !existingOutputDefinition.isRequired()
241 .equals(newOutputDefinition.isRequired())) {
242 modifiedOutputDefinitionNames.add(outputName);
245 return modifiedOutputDefinitionNames;
248 private Either<Boolean, ResponseFormat> getMappedOutputErrorResponse(ResponseFormatManager responseFormatManager,
249 Set<String> modifiedMappedOutputs, String message,
250 ActionStatus errorStatus) {
251 String modifiedOutputNameList = String.join(",", modifiedMappedOutputs);
252 LOGGER.error(message, modifiedOutputNameList);
253 ResponseFormat errorResponse = responseFormatManager.getResponseFormat(errorStatus, modifiedOutputNameList);
254 return Either.right(errorResponse);
257 protected ResponseFormatManager getResponseFormatManager() {
258 return ResponseFormatManager.getInstance();
261 private Either<Boolean, ResponseFormat> isInterfaceOperationTypeValid(Operation interfaceOperation, ResponseFormatManager responseFormatManager,
262 InterfaceDefinition interfaceDefinition, boolean isUpdate) {
263 Either<Boolean, ResponseFormat> operationTypeEmptyEither = isOperationTypeEmpty(responseFormatManager, interfaceOperation.getName());
264 if (operationTypeEmptyEither.isRight()) {
265 return Either.right(operationTypeEmptyEither.right().value());
267 Either<Boolean, ResponseFormat> operationTypeRegexValidationResponse = isOperationTypeRegexValid(responseFormatManager,
268 interfaceOperation.getName());
269 if (operationTypeRegexValidationResponse.isRight()) {
270 return Either.right(operationTypeRegexValidationResponse.right().value());
272 Either<Boolean, ResponseFormat> operationTypeUniqueResponse = validateOperationTypeUnique(interfaceOperation, interfaceDefinition, isUpdate);
273 if (operationTypeUniqueResponse.isRight()) {
274 return Either.right(operationTypeUniqueResponse.right().value());
276 if (!operationTypeUniqueResponse.left().value()) {
277 LOGGER.error("Interface Operation type {} already in use ", interfaceOperation.getName());
278 ResponseFormat errorResponse = responseFormatManager
279 .getResponseFormat(ActionStatus.INTERFACE_OPERATION_NAME_ALREADY_IN_USE, interfaceOperation.getName());
280 return Either.right(errorResponse);
282 return Either.left(Boolean.TRUE);
285 private Either<Boolean, ResponseFormat> validateInputParameters(Operation interfaceOperation, ResponseFormatManager responseFormatManager) {
286 if (isInputParameterNameEmpty(interfaceOperation)) {
287 LOGGER.error("Interface operation input parameter name can't be empty");
288 ResponseFormat inputResponse = responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_INPUT_NAME_MANDATORY);
289 return Either.right(inputResponse);
291 Either<Boolean, Set<String>> validateInputParametersUniqueResponse = isInputParametersUnique(interfaceOperation);
292 if (validateInputParametersUniqueResponse.isRight()) {
293 LOGGER.error("Interface operation input parameter names {} already in use", validateInputParametersUniqueResponse.right().value());
294 ResponseFormat inputResponse = responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_INPUT_NAME_ALREADY_IN_USE,
295 validateInputParametersUniqueResponse.right().value().toString());
296 return Either.right(inputResponse);
298 return Either.left(Boolean.TRUE);
301 private Either<Boolean, ResponseFormat> validateOutputParameters(Operation interfaceOperation, ResponseFormatManager responseFormatManager) {
302 if (isOutputParameterNameEmpty(interfaceOperation)) {
303 LOGGER.error("Interface operation output parameter name can't be empty");
304 ResponseFormat inputResponse = responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_OUTPUT_NAME_MANDATORY);
305 return Either.right(inputResponse);
307 Either<Boolean, Set<String>> validateOutputParametersUniqueResponse = isOutputParametersUnique(interfaceOperation);
308 if (validateOutputParametersUniqueResponse.isRight()) {
309 LOGGER.error("Interface operation output parameter names {} already in use", validateOutputParametersUniqueResponse.right().value());
310 ResponseFormat inputResponse = responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_OUTPUT_NAME_ALREADY_IN_USE,
311 validateOutputParametersUniqueResponse.right().value().toString());
312 return Either.right(inputResponse);
314 return Either.left(Boolean.TRUE);
317 private Either<Boolean, ResponseFormat> isOperationTypeEmpty(ResponseFormatManager responseFormatManager, String operationType) {
318 if (StringUtils.isEmpty(operationType)) {
319 LOGGER.error("Interface Operation type is mandatory");
320 ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NAME_MANDATORY);
321 return Either.right(errorResponse);
323 return Either.left(Boolean.TRUE);
326 private Either<Boolean, ResponseFormat> isOperationTypeRegexValid(ResponseFormatManager responseFormatManager, String operationType) {
327 if (!isValidOperationType(operationType)) {
328 LOGGER.error("Interface Operation type {} is invalid, Operation type should not contain"
329 + "Special character, space, numbers and should not be greater than 200 characters", operationType);
330 ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NAME_INVALID, operationType);
331 return Either.right(errorResponse);
333 return Either.left(Boolean.TRUE);
336 private Either<Boolean, ResponseFormat> validateOperationTypeUnique(Operation interfaceOperation, InterfaceDefinition interfaceDefinition,
338 boolean isOperationTypeUnique = false;
339 if (interfaceDefinition == null || CollectionUtils.isEmpty(interfaceDefinition.getOperationsMap().values())) {
340 return Either.left(true);
342 Map<String, String> operationTypes = new HashMap<>();
343 interfaceDefinition.getOperationsMap().values()
344 .forEach(operationType -> operationTypes.put(operationType.getUniqueId(), operationType.getName()));
345 if (!operationTypes.values().contains(interfaceOperation.getName())) {
346 isOperationTypeUnique = true;
348 if (!isOperationTypeUnique && isUpdate) {
349 Optional<String> id = operationTypes.entrySet().stream().filter(entry -> Objects.equals(entry.getValue(), interfaceOperation.getName()))
350 .map(Map.Entry::getKey).findAny();
351 if (id.isPresent() && id.get().equalsIgnoreCase(interfaceOperation.getUniqueId())) {
352 isOperationTypeUnique = true;
355 return Either.left(isOperationTypeUnique);
358 private Boolean isInputParameterNameEmpty(Operation operationDataDefinition) {
359 return operationDataDefinition.getInputs().getListToscaDataDefinition().stream()
360 .anyMatch(inputParam -> inputParam.getName() == null || inputParam.getName().trim().equals(StringUtils.EMPTY));
363 private Either<Boolean, Set<String>> isInputParametersUnique(Operation operationDataDefinition) {
364 Set<String> inputParamNamesSet = new HashSet<>();
365 Set<String> duplicateParamNamesToReturn = new HashSet<>();
366 operationDataDefinition.getInputs().getListToscaDataDefinition().forEach(inputParam -> {
367 if (!inputParamNamesSet.add(inputParam.getName().trim())) {
368 duplicateParamNamesToReturn.add(inputParam.getName().trim());
371 if (!duplicateParamNamesToReturn.isEmpty()) {
372 return Either.right(duplicateParamNamesToReturn);
374 return Either.left(Boolean.TRUE);
377 private Boolean isOutputParameterNameEmpty(Operation operationDataDefinition) {
378 return operationDataDefinition.getOutputs().getListToscaDataDefinition().stream()
379 .anyMatch(outputParam -> outputParam.getName() == null || outputParam.getName().trim().equals(StringUtils.EMPTY));
382 private Either<Boolean, Set<String>> isOutputParametersUnique(Operation operationDataDefinition) {
383 Set<String> outputParamNamesSet = new HashSet<>();
384 Set<String> duplicateParamNamesToReturn = new HashSet<>();
385 operationDataDefinition.getOutputs().getListToscaDataDefinition().forEach(outputParam -> {
386 if (!outputParamNamesSet.add(outputParam.getName().trim())) {
387 duplicateParamNamesToReturn.add(outputParam.getName().trim());
390 if (!duplicateParamNamesToReturn.isEmpty()) {
391 return Either.right(duplicateParamNamesToReturn);
393 return Either.left(Boolean.TRUE);
396 private Either<Boolean, ResponseFormat> validateInputPropertyExistInComponent(Operation operation, InterfaceDefinition inputInterfaceDefinition,
397 org.openecomp.sdc.be.model.Component component,
398 ResponseFormatManager responseFormatManager) {
399 boolean isOperationInputToInputPropertyMappingValid = false;
400 boolean isOperationInputToOtherOperationOutputMappingValid = false;
401 String mappingName = "";
402 List<OperationInputDefinition> inputListToscaDataDefinition = operation.getInputs().getListToscaDataDefinition();
403 for (OperationInputDefinition inputDefinition : inputListToscaDataDefinition) {
404 if (isOperationInputMappedToComponentInput(inputDefinition, component.getInputs()) || isCapabilityProperty(inputDefinition.getInputId(),
405 component).isPresent()) {
406 isOperationInputToInputPropertyMappingValid = true;
408 mappingName = inputDefinition.getInputId().contains(".") ? inputDefinition.getInputId()
409 .substring(inputDefinition.getInputId().lastIndexOf('.') + 1) : inputDefinition.getInputId();
413 if (isOperationInputToInputPropertyMappingValid) {
414 return Either.left(Boolean.TRUE);
416 //Mapped property not found in the component properties.. Check in other operation output parameters of
418 // component (other operation => not having the same full name)
419 String actualOperationIdentifier = inputInterfaceDefinition.getType() + "." + operation.getName();
420 ListDataDefinition<OperationOutputDefinition> outputListDataDefinition = getOtherOperationOutputsOfComponent(actualOperationIdentifier,
421 component.getInterfaces());
422 List<OperationOutputDefinition> componentOutputsFromOtherOperations = outputListDataDefinition.getListToscaDataDefinition();
423 if (validateOutputExistsInComponent(mappingName, componentOutputsFromOtherOperations)) {
424 isOperationInputToOtherOperationOutputMappingValid = true;
426 //Get the output parameter display name from the full name
427 mappingName = getOperationOutputName(mappingName);
429 if (!isOperationInputToOtherOperationOutputMappingValid) {
430 LOGGER.error("Interface operation input parameter property {} not found in component input properties or"
431 + "capability properties or outputs of other operations.", mappingName);
432 ResponseFormat inputResponse = responseFormatManager
433 .getResponseFormat(ActionStatus.INTERFACE_OPERATION_INPUT_PROPERTY_NOT_FOUND_IN_COMPONENT, mappingName,
434 component.getComponentType().getValue());
435 return Either.right(inputResponse);
437 return Either.left(Boolean.TRUE);
440 private boolean validateOutputExistsInComponent(String mappedOutputName, List<OperationOutputDefinition> outputs) {
441 return outputs.stream().anyMatch(output -> output.getName().equals(mappedOutputName));
445 * Get the input definitions of other operations of the component from current as well as other interfaces.
447 * @param currentOperationIdentifier Identifier for the request operation (interface_name.operation_name)
448 * @param componentInterfaces Interfaces of the component
450 private List<OperationInputDefinition> getOtherOperationInputsOfComponent(String currentOperationIdentifier,
451 Map<String, InterfaceDefinition> componentInterfaces) {
452 List<OperationInputDefinition> otherOperationInputs = new ArrayList<>();
453 if (MapUtils.isEmpty(componentInterfaces)) {
454 return otherOperationInputs;
456 for (Map.Entry<String, InterfaceDefinition> interfaceDefinitionEntry : componentInterfaces.entrySet()) {
457 final Map<String, OperationDataDefinition> operations = interfaceDefinitionEntry.getValue().getOperations();
458 if (MapUtils.isEmpty(operations)) {
461 for (Map.Entry<String, OperationDataDefinition> operationEntry : operations.entrySet()) {
462 ListDataDefinition<OperationInputDefinition> inputs = operationEntry.getValue().getInputs();
463 String expectedOperationIdentifier = interfaceDefinitionEntry.getValue().getType() + "." + operationEntry.getValue().getName();
464 if (!currentOperationIdentifier.equals(expectedOperationIdentifier) && Objects.nonNull(inputs) && !inputs.isEmpty()) {
465 otherOperationInputs.addAll(inputs.getListToscaDataDefinition());
469 return otherOperationInputs;
473 * Get the output of an operation in an interface.
475 * @param inputOperationId Unique identifier for the request operation
476 * @param componentInterfaces Interfaces of the component
478 private List<OperationOutputDefinition> getInterfaceOperationOutputs(String inputOperationId,
479 Map<String, InterfaceDefinition> componentInterfaces) {
480 List<OperationOutputDefinition> operationOutputDefinitions = new ArrayList<>();
481 if (MapUtils.isEmpty(componentInterfaces)) {
482 return operationOutputDefinitions;
484 for (Map.Entry<String, InterfaceDefinition> interfaceDefinitionEntry : componentInterfaces.entrySet()) {
485 final Map<String, OperationDataDefinition> operations = interfaceDefinitionEntry.getValue().getOperations();
486 if (MapUtils.isEmpty(operations)) {
489 for (Map.Entry<String, OperationDataDefinition> operationEntry : operations.entrySet()) {
490 String expectedOperationId = operationEntry.getValue().getUniqueId();
491 if (expectedOperationId.equals(inputOperationId)) {
492 ListDataDefinition<OperationOutputDefinition> operationOutputs = operationEntry.getValue().getOutputs();
493 return (Objects.isNull(operationOutputs) || operationOutputs.isEmpty()) ? operationOutputDefinitions
494 : operationOutputs.getListToscaDataDefinition();
498 return operationOutputDefinitions;
501 private boolean isValidOperationType(String operationType) {
502 return Pattern.matches(TYPE_VALIDATION_REGEX, operationType);