Update vulnerable package dependencies
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / validation / InterfaceOperationValidation.java
1 /*
2  * Copyright © 2016-2018 European Support Limited
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 package org.openecomp.sdc.be.components.validation;
17
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;
22
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;
30 import java.util.Map;
31 import java.util.Objects;
32 import java.util.Optional;
33 import java.util.Set;
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;
53
54 @Component("interfaceOperationValidation")
55 public class InterfaceOperationValidation {
56
57     private static final String TYPE_VALIDATION_REGEX = "^[a-zA-Z0-9_]{1,200}$";
58     private static final Logger LOGGER = LoggerFactory.getLogger(InterfaceOperationValidation.class);
59
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;
68         }
69         Either<Boolean, ResponseFormat> validateOperationNameUniqueness = validateOperationNameUniquenessInCollection(
70             inputInterfaceDefinition.getOperationsMap().values());
71         if (validateOperationNameUniqueness.isRight()) {
72             return validateOperationNameUniqueness;
73         }
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;
79             }
80         }
81         return Either.left(Boolean.TRUE);
82     }
83
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);
92         }
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);
103         }
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);
108         }
109         return Either.left(Boolean.TRUE);
110     }
111
112     private Either<Boolean, ResponseFormat> validateAllowedOperationsOnGlobalInterfaceType(InterfaceDefinition interfaceDefinition,
113                                                                                            Map<String, InterfaceDefinition> globalInterfaceTypes) {
114         if (globalInterfaceTypes == null) {
115             return Either.left(Boolean.TRUE);
116         }
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()));
125         }
126         return Either.left(Boolean.TRUE);
127     }
128
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())) {
133                 return Either
134                     .right(getResponseFormatManager().getResponseFormat(ActionStatus.INTERFACE_OPERATION_NAME_ALREADY_IN_USE, operation.getName()));
135             }
136         }
137         return Either.left(Boolean.TRUE);
138     }
139
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());
148         }
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());
153             }
154             Either<Boolean, ResponseFormat> inputPropertyExistInComponent = validateInputPropertyExistInComponent(interfaceOperation,
155                 inputInterfaceDefinition, component, responseFormatManager);
156             if (inputPropertyExistInComponent.isRight()) {
157                 return Either.right(inputPropertyExistInComponent.right().value());
158             }
159         }
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());
164             }
165         }
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());
171             }
172         }
173         return Either.left(Boolean.TRUE);
174     }
175
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);
184         }
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());
192         }
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);
201         }
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);
212             }
213         }
214         return Either.left(Boolean.TRUE);
215     }
216
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());
222     }
223
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));
228     }
229
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);
243             }
244         }
245         return modifiedOutputDefinitionNames;
246     }
247
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);
255     }
256
257     protected ResponseFormatManager getResponseFormatManager() {
258         return ResponseFormatManager.getInstance();
259     }
260
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());
266         }
267         Either<Boolean, ResponseFormat> operationTypeRegexValidationResponse = isOperationTypeRegexValid(responseFormatManager,
268             interfaceOperation.getName());
269         if (operationTypeRegexValidationResponse.isRight()) {
270             return Either.right(operationTypeRegexValidationResponse.right().value());
271         }
272         Either<Boolean, ResponseFormat> operationTypeUniqueResponse = validateOperationTypeUnique(interfaceOperation, interfaceDefinition, isUpdate);
273         if (operationTypeUniqueResponse.isRight()) {
274             return Either.right(operationTypeUniqueResponse.right().value());
275         }
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);
281         }
282         return Either.left(Boolean.TRUE);
283     }
284
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);
290         }
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);
297         }
298         return Either.left(Boolean.TRUE);
299     }
300
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);
306         }
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);
313         }
314         return Either.left(Boolean.TRUE);
315     }
316
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);
322         }
323         return Either.left(Boolean.TRUE);
324     }
325
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);
332         }
333         return Either.left(Boolean.TRUE);
334     }
335
336     private Either<Boolean, ResponseFormat> validateOperationTypeUnique(Operation interfaceOperation, InterfaceDefinition interfaceDefinition,
337                                                                         boolean isUpdate) {
338         boolean isOperationTypeUnique = false;
339         if (interfaceDefinition == null || CollectionUtils.isEmpty(interfaceDefinition.getOperationsMap().values())) {
340             return Either.left(true);
341         }
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;
347         }
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;
353             }
354         }
355         return Either.left(isOperationTypeUnique);
356     }
357
358     private Boolean isInputParameterNameEmpty(Operation operationDataDefinition) {
359         return operationDataDefinition.getInputs().getListToscaDataDefinition().stream()
360             .anyMatch(inputParam -> inputParam.getName() == null || inputParam.getName().trim().equals(StringUtils.EMPTY));
361     }
362
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());
369             }
370         });
371         if (!duplicateParamNamesToReturn.isEmpty()) {
372             return Either.right(duplicateParamNamesToReturn);
373         }
374         return Either.left(Boolean.TRUE);
375     }
376
377     private Boolean isOutputParameterNameEmpty(Operation operationDataDefinition) {
378         return operationDataDefinition.getOutputs().getListToscaDataDefinition().stream()
379             .anyMatch(outputParam -> outputParam.getName() == null || outputParam.getName().trim().equals(StringUtils.EMPTY));
380     }
381
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());
388             }
389         });
390         if (!duplicateParamNamesToReturn.isEmpty()) {
391             return Either.right(duplicateParamNamesToReturn);
392         }
393         return Either.left(Boolean.TRUE);
394     }
395
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;
407             } else {
408                 mappingName = inputDefinition.getInputId().contains(".") ? inputDefinition.getInputId()
409                     .substring(inputDefinition.getInputId().lastIndexOf('.') + 1) : inputDefinition.getInputId();
410                 break;
411             }
412         }
413         if (isOperationInputToInputPropertyMappingValid) {
414             return Either.left(Boolean.TRUE);
415         }
416         //Mapped property not found in the component properties.. Check in other operation output parameters of
417
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;
425         } else {
426             //Get the output parameter display name from the full name
427             mappingName = getOperationOutputName(mappingName);
428         }
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);
436         }
437         return Either.left(Boolean.TRUE);
438     }
439
440     private boolean validateOutputExistsInComponent(String mappedOutputName, List<OperationOutputDefinition> outputs) {
441         return outputs.stream().anyMatch(output -> output.getName().equals(mappedOutputName));
442     }
443
444     /**
445      * Get the input definitions of other operations of the component from current as well as other interfaces.
446      *
447      * @param currentOperationIdentifier Identifier for the request operation (interface_name.operation_name)
448      * @param componentInterfaces        Interfaces of the component
449      */
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;
455         }
456         for (Map.Entry<String, InterfaceDefinition> interfaceDefinitionEntry : componentInterfaces.entrySet()) {
457             final Map<String, OperationDataDefinition> operations = interfaceDefinitionEntry.getValue().getOperations();
458             if (MapUtils.isEmpty(operations)) {
459                 continue;
460             }
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());
466                 }
467             }
468         }
469         return otherOperationInputs;
470     }
471
472     /**
473      * Get the output of an operation in an interface.
474      *
475      * @param inputOperationId    Unique identifier for the request operation
476      * @param componentInterfaces Interfaces of the component
477      */
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;
483         }
484         for (Map.Entry<String, InterfaceDefinition> interfaceDefinitionEntry : componentInterfaces.entrySet()) {
485             final Map<String, OperationDataDefinition> operations = interfaceDefinitionEntry.getValue().getOperations();
486             if (MapUtils.isEmpty(operations)) {
487                 continue;
488             }
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();
495                 }
496             }
497         }
498         return operationOutputDefinitions;
499     }
500
501     private boolean isValidOperationType(String operationType) {
502         return Pattern.matches(TYPE_VALIDATION_REGEX, operationType);
503     }
504 }