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