b876782ce466fd8f6a5ec9704d51681f583ede7d
[sdc.git] /
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
17 package org.openecomp.sdc.be.components.validation;
18
19 import com.google.common.collect.Sets;
20 import fj.data.Either;
21 import org.apache.commons.collections.CollectionUtils;
22 import org.apache.commons.collections.MapUtils;
23 import org.apache.commons.lang.StringUtils;
24 import org.openecomp.sdc.be.components.impl.ResponseFormatManager;
25 import org.openecomp.sdc.be.components.utils.InterfaceOperationUtils;
26 import org.openecomp.sdc.be.dao.api.ActionStatus;
27 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
28 import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
29 import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
30 import org.openecomp.sdc.be.datatypes.elements.OperationOutputDefinition;
31 import org.openecomp.sdc.be.model.InterfaceDefinition;
32 import org.openecomp.sdc.be.model.Operation;
33 import org.openecomp.sdc.exception.ResponseFormat;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36 import org.springframework.stereotype.Component;
37
38 import java.util.ArrayList;
39 import java.util.Collection;
40 import java.util.HashMap;
41 import java.util.HashSet;
42 import java.util.List;
43 import java.util.Map;
44 import java.util.Objects;
45 import java.util.Optional;
46 import java.util.Set;
47 import java.util.regex.Pattern;
48 import java.util.stream.Collectors;
49 import java.util.stream.Stream;
50
51 import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.getOperationOutputName;
52 import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.getOtherOperationOutputsOfComponent;
53 import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.isOperationInputMappedToComponentInput;
54 import static org.openecomp.sdc.be.components.utils.PropertiesUtils.isCapabilityProperty;
55
56 @Component("interfaceOperationValidation")
57 public class InterfaceOperationValidation {
58
59     private static final String TYPE_VALIDATION_REGEX = "^[a-zA-Z0-9_]{1,200}$";
60
61     private static final Logger LOGGER = LoggerFactory.getLogger(InterfaceOperationValidation.class);
62
63     public Either<Boolean, ResponseFormat> validateInterfaceOperations(
64             InterfaceDefinition inputInterfaceDefinition, org.openecomp.sdc.be.model.Component component,
65             InterfaceDefinition storedInterfaceDefinition, Map<String, InterfaceDefinition> globalInterfaceTypes,
66             boolean isUpdate) {
67
68         Either<Boolean, ResponseFormat> validateAllowedOperationsOnGlobalInterfaceType =
69                 validateAllowedOperationsOnGlobalInterfaceType(inputInterfaceDefinition, globalInterfaceTypes);
70         if (validateAllowedOperationsOnGlobalInterfaceType.isRight()) {
71             return validateAllowedOperationsOnGlobalInterfaceType;
72         }
73
74         Either<Boolean, ResponseFormat> validateOperationNameUniqueness =
75                 validateOperationNameUniquenessInCollection(inputInterfaceDefinition.getOperationsMap().values());
76         if (validateOperationNameUniqueness.isRight()) {
77             return validateOperationNameUniqueness;
78         }
79
80         for (Operation interfaceOperation : inputInterfaceDefinition.getOperationsMap().values()) {
81             Either<Boolean, ResponseFormat> interfaceOperationValidatorResponse = validateInterfaceOperation(
82                     interfaceOperation, storedInterfaceDefinition, inputInterfaceDefinition, component, isUpdate);
83             if (interfaceOperationValidatorResponse.isRight()) {
84                 return interfaceOperationValidatorResponse;
85             }
86         }
87
88         return Either.left(Boolean.TRUE);
89     }
90
91     public Either<Boolean, ResponseFormat> validateDeleteOperationContainsNoMappedOutput(
92             Operation interfaceOperationToDelete, org.openecomp.sdc.be.model.Component component,
93             InterfaceDefinition storedInterfaceDefinition) {
94         ResponseFormatManager responseFormatManager = getResponseFormatManager();
95         List<OperationOutputDefinition> existingOperationOutputs =
96                 getInterfaceOperationOutputs(interfaceOperationToDelete.getUniqueId(), component.getInterfaces());
97         if (existingOperationOutputs.isEmpty()) {
98             return Either.left(Boolean.TRUE);
99         }
100         String mappedOutputPrefix = storedInterfaceDefinition.getType() + "." + interfaceOperationToDelete.getName();
101         List<OperationInputDefinition> interfaceOperationInputs =
102                 getOtherOperationInputsOfComponent(mappedOutputPrefix, component.getInterfaces());
103         Set<String> mappedOutputsInDeletedOperation = new HashSet<>();
104         Set<String> existingOperationOutputNames = existingOperationOutputs.stream()
105                 .map(OperationOutputDefinition::getName)
106                 .collect(Collectors.toSet());
107         for (String existingOperationOutputName : existingOperationOutputNames) {
108             Set<String> matchedOutputsMappedToInputs = interfaceOperationInputs.stream()
109                     .filter(operationInputDefinition -> operationInputDefinition.getInputId()
110                             .equals(mappedOutputPrefix + "." + existingOperationOutputName))
111                     .map(operationInputDefinition -> getOperationOutputName(operationInputDefinition.getInputId()))
112                     .collect(Collectors.toSet());
113             mappedOutputsInDeletedOperation.addAll(matchedOutputsMappedToInputs);
114         }
115
116         if (CollectionUtils.isNotEmpty(mappedOutputsInDeletedOperation)) {
117             return getMappedOutputErrorResponse(responseFormatManager, mappedOutputsInDeletedOperation,
118                     "Cannot delete interface operation with output(s) '{}' mapped to another operation input",
119                     ActionStatus.INTERFACE_OPERATION_DELETE_WITH_MAPPED_OUTPUT);
120         }
121         return Either.left(Boolean.TRUE);
122     }
123
124     private Either<Boolean, ResponseFormat> validateAllowedOperationsOnGlobalInterfaceType(
125             InterfaceDefinition interfaceDefinition, Map<String, InterfaceDefinition> globalInterfaceTypes) {
126
127         if (globalInterfaceTypes == null) {
128             return Either.left(Boolean.TRUE);
129         }
130         boolean isOperationValidOnGlobalInterfaceType = Stream.of(interfaceDefinition)
131                 .filter(interfaceDef -> globalInterfaceTypes.values().stream().anyMatch(interfaceDef1 ->
132                         interfaceDef1.getType().equalsIgnoreCase(interfaceDef.getType())))
133                 .flatMap(interfaceDef -> interfaceDef.getOperationsMap().values().stream().map(Operation::getName))
134                 .allMatch(operationName -> globalInterfaceTypes.values().stream()
135                         .flatMap(interfaceDef -> interfaceDef.getOperationsMap().keySet().stream())
136                         .anyMatch(opName -> opName.equalsIgnoreCase(operationName)));
137         if (!isOperationValidOnGlobalInterfaceType) {
138             return Either.right(getResponseFormatManager()
139                     .getResponseFormat(ActionStatus.INTERFACE_OPERATION_INVALID_FOR_GLOBAL_TYPE,
140                             interfaceDefinition.getType()));
141         }
142         return Either.left(Boolean.TRUE);
143     }
144
145     private Either<Boolean, ResponseFormat> validateOperationNameUniquenessInCollection(
146             Collection<Operation> operationList) {
147         HashSet<String> operationNames = new HashSet<>();
148         for (Operation operation : operationList) {
149             if (!operationNames.add(operation.getName())) {
150                 return Either.right(getResponseFormatManager()
151                                             .getResponseFormat(ActionStatus.INTERFACE_OPERATION_NAME_ALREADY_IN_USE,
152                                                     operation.getName()));
153             }
154         }
155         return Either.left(Boolean.TRUE);
156     }
157
158     private Either<Boolean, ResponseFormat> validateInterfaceOperation(Operation interfaceOperation,
159             InterfaceDefinition storedInterfaceDefinition, InterfaceDefinition inputInterfaceDefinition,
160             org.openecomp.sdc.be.model.Component component, boolean isUpdate) {
161
162         ResponseFormatManager responseFormatManager = getResponseFormatManager();
163         Either<Boolean, ResponseFormat> interfaceOperationTypeResponse =
164                 isInterfaceOperationTypeValid(interfaceOperation, responseFormatManager, storedInterfaceDefinition,
165                         isUpdate);
166         if (interfaceOperationTypeResponse.isRight()) {
167             return Either.right(interfaceOperationTypeResponse.right().value());
168         }
169
170         if (null != interfaceOperation.getInputs()
171                 && CollectionUtils.isNotEmpty(interfaceOperation.getInputs().getListToscaDataDefinition())) {
172             Either<Boolean, ResponseFormat> inputParametersResponse =
173                     validateInputParameters(interfaceOperation, responseFormatManager);
174             if (inputParametersResponse.isRight()) {
175                 return Either.right(inputParametersResponse.right().value());
176             }
177
178             Either<Boolean, ResponseFormat> inputPropertyExistInComponent =
179                     validateInputPropertyExistInComponent(interfaceOperation,
180                             inputInterfaceDefinition, component, responseFormatManager);
181             if (inputPropertyExistInComponent.isRight()) {
182                 return Either.right(inputPropertyExistInComponent.right().value());
183             }
184         }
185
186         if (null != interfaceOperation.getOutputs()
187                 && CollectionUtils.isNotEmpty(interfaceOperation.getOutputs().getListToscaDataDefinition())) {
188             Either<Boolean, ResponseFormat> outputParametersResponse =
189                     validateOutputParameters(interfaceOperation, responseFormatManager);
190             if (outputParametersResponse.isRight()) {
191                 return Either.right(outputParametersResponse.right().value());
192             }
193         }
194
195         if (MapUtils.isNotEmpty(component.getInterfaces()) && isUpdate) {
196             Either<Boolean, ResponseFormat> mappedOutputModifiedResponse =
197                     validateMappedOutputNotModified(interfaceOperation, component, inputInterfaceDefinition,
198                             responseFormatManager);
199             if (mappedOutputModifiedResponse.isRight()) {
200                 return Either.right(mappedOutputModifiedResponse.right().value());
201             }
202         }
203
204         return Either.left(Boolean.TRUE);
205     }
206
207
208     private Either<Boolean, ResponseFormat> validateMappedOutputNotModified(Operation interfaceOperation,
209             org.openecomp.sdc.be.model.Component component, InterfaceDefinition interfaceDefinition,
210             ResponseFormatManager responseFormatManager) {
211
212         List<OperationOutputDefinition> existingOperationOutputs =
213                 getInterfaceOperationOutputs(interfaceOperation.getUniqueId(), component.getInterfaces());
214         if (existingOperationOutputs.isEmpty()) {
215             return Either.left(Boolean.TRUE);
216         }
217         Set<String> existingOperationOutputNames = existingOperationOutputs.stream()
218                 .map(OperationOutputDefinition::getName)
219                 .collect(Collectors.toSet());
220
221         ListDataDefinition<OperationOutputDefinition> currentOutputs = interfaceOperation.getOutputs();
222         Set<String> currentOperationOutputNames = new HashSet<>();
223         if (currentOutputs != null && !currentOutputs.isEmpty()) {
224             currentOperationOutputNames = currentOutputs.getListToscaDataDefinition().stream()
225                     .map(OperationOutputDefinition::getName)
226                     .collect(Collectors.toSet());
227         }
228         String mappedOutputPrefix = interfaceDefinition.getType() + "." + interfaceOperation.getName();
229         //Get the deleted outputs (name changed also equivalent to deleted)
230         Set<String> deletedOutputs = Sets.difference(existingOperationOutputNames, currentOperationOutputNames);
231         Set<String> deletedMappedOutputs = getModifiedMappedOutputs(deletedOutputs, mappedOutputPrefix,
232                 component.getInterfaces());
233
234         if (CollectionUtils.isNotEmpty(deletedMappedOutputs)) {
235             return getMappedOutputErrorResponse(responseFormatManager, deletedMappedOutputs,
236                     "Cannot update or delete interface operation output(s) '{}' mapped to an operation input",
237                     ActionStatus.INTERFACE_OPERATION_MAPPED_OUTPUT_MODIFIED);
238         }
239
240         if (currentOutputs != null && !currentOutputs.isEmpty()) {
241             //Get the unchanged outputs based on name to see if other attributes (type/mandatory) have not been changed
242             Set<String> unchangedOutputNames = Sets.intersection(existingOperationOutputNames,
243                     currentOperationOutputNames);
244             Set<String> modifiedOutputNames =
245                     getModifiedOutputNames(currentOutputs.getListToscaDataDefinition(),
246                             existingOperationOutputs, unchangedOutputNames);
247             Set<String> modifiedMappedOutputNames = getModifiedMappedOutputs(modifiedOutputNames, mappedOutputPrefix,
248                     component.getInterfaces());
249             if (CollectionUtils.isNotEmpty(modifiedMappedOutputNames)) {
250                 return getMappedOutputErrorResponse(responseFormatManager, modifiedMappedOutputNames,
251                         "Cannot update or delete interface operation output(s) '{}' mapped to an operation input",
252                         ActionStatus.INTERFACE_OPERATION_MAPPED_OUTPUT_MODIFIED);
253             }
254         }
255
256         return Either.left(Boolean.TRUE);
257     }
258
259     private Set<String> getModifiedMappedOutputs(Set<String> modifiedOutputNames, String mappedOutputPrefix,
260                                                  Map<String, InterfaceDefinition> componentInterfaces) {
261         return modifiedOutputNames.stream()
262                 .filter(modifiedOutputName -> isMappedOutputModified(mappedOutputPrefix, modifiedOutputName,
263                         componentInterfaces))
264                 .map(InterfaceOperationUtils::getOperationOutputName)
265                 .collect(Collectors.toSet());
266     }
267
268     private boolean isMappedOutputModified(String mappedOutputPrefix, String outputName,
269                                            Map<String, InterfaceDefinition> componentInterfaces) {
270         List<OperationInputDefinition> interfaceOperationInputs =
271                 getOtherOperationInputsOfComponent(mappedOutputPrefix, componentInterfaces);
272         return interfaceOperationInputs.stream()
273                 .anyMatch(operationInputDefinition -> operationInputDefinition.getInputId()
274                         .equals(mappedOutputPrefix + "." + outputName));
275     }
276
277     private static Set<String> getModifiedOutputNames(List<OperationOutputDefinition> currentOperationOutputs,
278                                                       List<OperationOutputDefinition> existingOperationOutputs,
279                                                       Set<String> unchangedOutputNames) {
280         Set<String> modifiedOutputDefinitionNames = new HashSet<>();
281         Map<String, OperationOutputDefinition> newOutputMap = currentOperationOutputs.stream()
282                 .collect(Collectors.toMap(OperationOutputDefinition::getName,
283                         (OperationOutputDefinition operationOutputDefinition) -> operationOutputDefinition));
284
285         Map<String, OperationOutputDefinition> existingOutputMap = existingOperationOutputs.stream()
286                 .collect(Collectors.toMap(OperationOutputDefinition::getName,
287                         (OperationOutputDefinition operationOutputDefinition) -> operationOutputDefinition));
288
289         for (String outputName : unchangedOutputNames) {
290             OperationOutputDefinition existingOutputDefinition = existingOutputMap.get(outputName);
291             OperationOutputDefinition newOutputDefinition = newOutputMap.get(outputName);
292             if (!existingOutputDefinition.getType().equals(newOutputDefinition.getType())
293                         || !existingOutputDefinition.isRequired().equals(newOutputDefinition.isRequired())) {
294                 modifiedOutputDefinitionNames.add(outputName);
295             }
296         }
297         return modifiedOutputDefinitionNames;
298     }
299
300     private Either<Boolean, ResponseFormat> getMappedOutputErrorResponse(ResponseFormatManager responseFormatManager,
301                                                                          Set<String> modifiedMappedOutputs,
302                                                                          String message,
303                                                                          ActionStatus errorStatus) {
304         String modifiedOutputNameList = String.join(",", modifiedMappedOutputs);
305         LOGGER.error(message, modifiedOutputNameList);
306         ResponseFormat errorResponse = responseFormatManager.getResponseFormat(errorStatus, modifiedOutputNameList);
307         return Either.right(errorResponse);
308     }
309
310
311     protected ResponseFormatManager getResponseFormatManager() {
312         return ResponseFormatManager.getInstance();
313     }
314
315     private Either<Boolean, ResponseFormat> isInterfaceOperationTypeValid(Operation interfaceOperation,
316                                                                           ResponseFormatManager responseFormatManager,
317                                                                           InterfaceDefinition interfaceDefinition,
318                                                                           boolean isUpdate) {
319
320         Either<Boolean, ResponseFormat> operationTypeEmptyEither =
321                 isOperationTypeEmpty(responseFormatManager, interfaceOperation.getName());
322         if (operationTypeEmptyEither.isRight()) {
323             return Either.right(operationTypeEmptyEither.right().value());
324         }
325
326         Either<Boolean, ResponseFormat> operationTypeRegexValidationResponse =
327                 isOperationTypeRegexValid(responseFormatManager, interfaceOperation.getName());
328         if (operationTypeRegexValidationResponse.isRight()) {
329             return Either.right(operationTypeRegexValidationResponse.right().value());
330         }
331
332         Either<Boolean, ResponseFormat> operationTypeUniqueResponse = validateOperationTypeUnique(interfaceOperation,
333                 interfaceDefinition, isUpdate);
334         if (operationTypeUniqueResponse.isRight()) {
335             return Either.right(operationTypeUniqueResponse.right().value());
336         }
337         if (!operationTypeUniqueResponse.left().value()) {
338             LOGGER.error("Interface Operation type  {} already in use ", interfaceOperation.getName());
339             ResponseFormat errorResponse = responseFormatManager.getResponseFormat(
340                     ActionStatus.INTERFACE_OPERATION_NAME_ALREADY_IN_USE, interfaceOperation.getName());
341             return Either.right(errorResponse);
342         }
343         return Either.left(Boolean.TRUE);
344     }
345
346     private Either<Boolean, ResponseFormat> validateInputParameters(Operation interfaceOperation,
347                                                                     ResponseFormatManager responseFormatManager) {
348         if (isInputParameterNameEmpty(interfaceOperation)) {
349             LOGGER.error("Interface operation input parameter name can't be empty");
350             ResponseFormat inputResponse =
351                     responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_INPUT_NAME_MANDATORY);
352             return Either.right(inputResponse);
353         }
354
355         Either<Boolean, Set<String>> validateInputParametersUniqueResponse =
356                 isInputParametersUnique(interfaceOperation);
357         if (validateInputParametersUniqueResponse.isRight()) {
358             LOGGER.error("Interface operation input parameter names {} already in use",
359                     validateInputParametersUniqueResponse.right().value());
360             ResponseFormat inputResponse =
361                     responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_INPUT_NAME_ALREADY_IN_USE,
362                             validateInputParametersUniqueResponse.right().value().toString());
363             return Either.right(inputResponse);
364         }
365         return Either.left(Boolean.TRUE);
366     }
367
368     private Either<Boolean, ResponseFormat> validateOutputParameters(Operation interfaceOperation,
369                                                                      ResponseFormatManager responseFormatManager) {
370         if (isOutputParameterNameEmpty(interfaceOperation)) {
371             LOGGER.error("Interface operation output parameter name can't be empty");
372             ResponseFormat inputResponse =
373                     responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_OUTPUT_NAME_MANDATORY);
374             return Either.right(inputResponse);
375         }
376
377         Either<Boolean, Set<String>> validateOutputParametersUniqueResponse =
378                 isOutputParametersUnique(interfaceOperation);
379         if (validateOutputParametersUniqueResponse.isRight()) {
380             LOGGER.error("Interface operation output parameter names {} already in use",
381                     validateOutputParametersUniqueResponse.right().value());
382             ResponseFormat inputResponse =
383                     responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_OUTPUT_NAME_ALREADY_IN_USE,
384                             validateOutputParametersUniqueResponse.right().value().toString());
385             return Either.right(inputResponse);
386         }
387         return Either.left(Boolean.TRUE);
388     }
389
390     private Either<Boolean, ResponseFormat> isOperationTypeEmpty(ResponseFormatManager responseFormatManager,
391             String operationType) {
392         if (StringUtils.isEmpty(operationType)) {
393             LOGGER.error("Interface Operation type is mandatory");
394             ResponseFormat errorResponse =
395                     responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NAME_MANDATORY);
396             return Either.right(errorResponse);
397         }
398         return Either.left(Boolean.TRUE);
399     }
400
401     private Either<Boolean, ResponseFormat> isOperationTypeRegexValid(ResponseFormatManager responseFormatManager,
402             String operationType) {
403         if (!isValidOperationType(operationType)) {
404             LOGGER.error("Interface Operation type {} is invalid, Operation type should not contain"
405                                  + "Special character, space, numbers and  should not be greater than 200 characters",
406                     operationType);
407             ResponseFormat errorResponse = responseFormatManager
408                                                    .getResponseFormat(ActionStatus.INTERFACE_OPERATION_NAME_INVALID,
409                                                            operationType);
410             return Either.right(errorResponse);
411         }
412         return Either.left(Boolean.TRUE);
413     }
414
415     private Either<Boolean, ResponseFormat> validateOperationTypeUnique(Operation interfaceOperation,
416             InterfaceDefinition interfaceDefinition, boolean isUpdate) {
417         boolean isOperationTypeUnique = false;
418
419         if (interfaceDefinition == null || CollectionUtils.isEmpty(interfaceDefinition.getOperationsMap().values())) {
420             return Either.left(true);
421         }
422
423         Map<String, String> operationTypes = new HashMap<>();
424         interfaceDefinition.getOperationsMap().values()
425                 .forEach(operationType -> operationTypes.put(operationType.getUniqueId(), operationType.getName()));
426
427         if (!operationTypes.values().contains(interfaceOperation.getName())) {
428             isOperationTypeUnique = true;
429         }
430         if (!isOperationTypeUnique && isUpdate) {
431             Optional<String> id = operationTypes.entrySet().stream().filter(entry -> Objects.equals(entry.getValue(),
432                     interfaceOperation.getName())).map(Map.Entry::getKey).findAny();
433             if (id.isPresent() && id.get().equalsIgnoreCase(interfaceOperation.getUniqueId())) {
434                 isOperationTypeUnique = true;
435             }
436         }
437
438         return Either.left(isOperationTypeUnique);
439     }
440
441     private Boolean isInputParameterNameEmpty(Operation operationDataDefinition) {
442         return operationDataDefinition.getInputs().getListToscaDataDefinition().stream().anyMatch(
443                 inputParam -> inputParam.getName() == null || inputParam.getName().trim().equals(StringUtils.EMPTY));
444     }
445
446
447     private Either<Boolean, Set<String>> isInputParametersUnique(Operation operationDataDefinition) {
448         Set<String> inputParamNamesSet = new HashSet<>();
449         Set<String> duplicateParamNamesToReturn = new HashSet<>();
450         operationDataDefinition.getInputs().getListToscaDataDefinition()
451                                .forEach(inputParam -> {
452                                    if (!inputParamNamesSet.add(inputParam.getName().trim())) {
453                                        duplicateParamNamesToReturn.add(inputParam.getName().trim());
454                                    }
455                                });
456         if (!duplicateParamNamesToReturn.isEmpty()) {
457             return Either.right(duplicateParamNamesToReturn);
458         }
459         return Either.left(Boolean.TRUE);
460     }
461
462     private Boolean isOutputParameterNameEmpty(Operation operationDataDefinition) {
463         return operationDataDefinition.getOutputs().getListToscaDataDefinition().stream().anyMatch(
464                 outputParam -> outputParam.getName() == null || outputParam.getName().trim().equals(StringUtils.EMPTY));
465     }
466
467     private Either<Boolean, Set<String>> isOutputParametersUnique(Operation operationDataDefinition) {
468         Set<String> outputParamNamesSet = new HashSet<>();
469         Set<String> duplicateParamNamesToReturn = new HashSet<>();
470         operationDataDefinition.getOutputs().getListToscaDataDefinition()
471                                .forEach(outputParam -> {
472                                    if (!outputParamNamesSet.add(outputParam.getName().trim())) {
473                                        duplicateParamNamesToReturn.add(outputParam.getName().trim());
474                                    }
475                                });
476         if (!duplicateParamNamesToReturn.isEmpty()) {
477             return Either.right(duplicateParamNamesToReturn);
478         }
479         return Either.left(Boolean.TRUE);
480     }
481
482     private  Either<Boolean, ResponseFormat> validateInputPropertyExistInComponent(Operation operation,
483             InterfaceDefinition inputInterfaceDefinition, org.openecomp.sdc.be.model.Component component,
484             ResponseFormatManager responseFormatManager) {
485
486         boolean isOperationInputToInputPropertyMappingValid = false;
487         boolean isOperationInputToOtherOperationOutputMappingValid = false;
488         String mappingName = "";
489         List<OperationInputDefinition> inputListToscaDataDefinition =
490                 operation.getInputs().getListToscaDataDefinition();
491         for (OperationInputDefinition inputDefinition : inputListToscaDataDefinition) {
492             if (isOperationInputMappedToComponentInput(inputDefinition, component.getInputs())
493                     || isCapabilityProperty(inputDefinition.getInputId(), component).isPresent()) {
494                 isOperationInputToInputPropertyMappingValid = true;
495             } else {
496                 mappingName = inputDefinition.getInputId().contains(".")
497                         ? inputDefinition.getInputId().substring(inputDefinition.getInputId().lastIndexOf('.') + 1)
498                         : inputDefinition.getInputId();
499                 break;
500             }
501         }
502         if (isOperationInputToInputPropertyMappingValid) {
503             return Either.left(Boolean.TRUE);
504         }
505
506         //Mapped property not found in the component properties.. Check in other operation output parameters of
507         // component (other operation => not having the same full name)
508         String actualOperationIdentifier = inputInterfaceDefinition.getType() + "." + operation.getName();
509         ListDataDefinition<OperationOutputDefinition> outputListDataDefinition =
510                 getOtherOperationOutputsOfComponent(actualOperationIdentifier, component.getInterfaces());
511
512         List<OperationOutputDefinition> componentOutputsFromOtherOperations =
513                 outputListDataDefinition.getListToscaDataDefinition();
514         if (validateOutputExistsInComponent(mappingName, componentOutputsFromOtherOperations)) {
515             isOperationInputToOtherOperationOutputMappingValid = true;
516         } else {
517             //Get the output parameter display name from the full name
518             mappingName = getOperationOutputName(mappingName);
519         }
520
521         if (!isOperationInputToOtherOperationOutputMappingValid) {
522             LOGGER.error("Interface operation input parameter property {} not found in component input properties or"
523                    + "capability properties or  outputs of other operations.", mappingName);
524             ResponseFormat inputResponse = responseFormatManager
525                     .getResponseFormat(ActionStatus.INTERFACE_OPERATION_INPUT_PROPERTY_NOT_FOUND_IN_COMPONENT,
526                             mappingName, component.getComponentType().getValue());
527             return Either.right(inputResponse);
528         }
529         return Either.left(Boolean.TRUE);
530     }
531
532     private boolean validateOutputExistsInComponent(String mappedOutputName,
533                                                     List<OperationOutputDefinition> outputs) {
534         return outputs.stream()
535                 .anyMatch(output -> output.getName().equals(mappedOutputName));
536     }
537
538     /**
539      * Get the input definitions of other operations of the component from current as well as other interfaces.
540      * @param currentOperationIdentifier Identifier for the request operation (interface_name.operation_name)
541      * @param componentInterfaces Interfaces of the component
542      */
543     private List<OperationInputDefinition> getOtherOperationInputsOfComponent(String currentOperationIdentifier,
544                                                                               Map<String, InterfaceDefinition>
545                                                                                       componentInterfaces) {
546         List<OperationInputDefinition> otherOperationInputs = new ArrayList<>();
547         if (MapUtils.isEmpty(componentInterfaces)) {
548             return otherOperationInputs;
549         }
550         for (Map.Entry<String, InterfaceDefinition> interfaceDefinitionEntry : componentInterfaces.entrySet()) {
551             final Map<String, OperationDataDefinition> operations = interfaceDefinitionEntry.getValue().getOperations();
552             if (MapUtils.isEmpty(operations)) {
553                 continue;
554             }
555             for (Map.Entry<String, OperationDataDefinition> operationEntry : operations.entrySet()) {
556                 ListDataDefinition<OperationInputDefinition> inputs = operationEntry.getValue().getInputs();
557                 String expectedOperationIdentifier =
558                         interfaceDefinitionEntry.getValue().getType() + "." + operationEntry.getValue().getName();
559                 if (!currentOperationIdentifier.equals(expectedOperationIdentifier) && Objects.nonNull(inputs) && !inputs.isEmpty()) {
560                     otherOperationInputs.addAll(inputs.getListToscaDataDefinition());
561                 }
562             }
563         }
564         return otherOperationInputs;
565     }
566
567     /**
568      * Get the output of an operation in an interface.
569      * @param inputOperationId Unique identifier for the request operation
570      * @param componentInterfaces Interfaces of the component
571      */
572     private List<OperationOutputDefinition> getInterfaceOperationOutputs(String inputOperationId,
573                                                                          Map<String, InterfaceDefinition>
574                                                                                  componentInterfaces) {
575         List<OperationOutputDefinition> operationOutputDefinitions = new ArrayList<>();
576         if (MapUtils.isEmpty(componentInterfaces)) {
577             return operationOutputDefinitions;
578         }
579         for (Map.Entry<String, InterfaceDefinition> interfaceDefinitionEntry : componentInterfaces.entrySet()) {
580             final Map<String, OperationDataDefinition> operations = interfaceDefinitionEntry.getValue().getOperations();
581             if (MapUtils.isEmpty(operations)) {
582                 continue;
583             }
584             for (Map.Entry<String, OperationDataDefinition> operationEntry : operations.entrySet()) {
585                 String expectedOperationId = operationEntry.getValue().getUniqueId();
586                 if (expectedOperationId.equals(inputOperationId)) {
587                     ListDataDefinition<OperationOutputDefinition> operationOutputs =
588                             operationEntry.getValue().getOutputs();
589                     return (Objects.isNull(operationOutputs) || operationOutputs.isEmpty())
590                             ? operationOutputDefinitions
591                             : operationOutputs.getListToscaDataDefinition();
592                 }
593             }
594         }
595         return operationOutputDefinitions;
596     }
597
598     private boolean isValidOperationType(String operationType) {
599         return Pattern.matches(TYPE_VALIDATION_REGEX, operationType);
600     }
601
602 }