2 * Copyright © 2016-2018 European Support Limited
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org.openecomp.sdc.be.components.validation;
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;
24 import com.google.common.collect.Sets;
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;
32 import java.util.Objects;
33 import java.util.Optional;
35 import java.util.regex.Pattern;
36 import java.util.stream.Collectors;
37 import java.util.stream.Stream;
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;
57 @Component("interfaceOperationValidation")
58 public class InterfaceOperationValidation {
60 private static final String TYPE_VALIDATION_REGEX = "^[a-zA-Z0-9_]{1,200}$";
62 private static final Logger LOGGER = LoggerFactory.getLogger(InterfaceOperationValidation.class);
64 public Either<Boolean, ResponseFormat> validateInterfaceOperations(
65 InterfaceDefinition inputInterfaceDefinition, org.openecomp.sdc.be.model.Component component,
66 InterfaceDefinition storedInterfaceDefinition, Map<String, InterfaceDefinition> globalInterfaceTypes,
69 Either<Boolean, ResponseFormat> validateAllowedOperationCountOnLocalInterfaceType =
70 validateAllowedOperationCountOnLocalInterfaceType(inputInterfaceDefinition, storedInterfaceDefinition,
71 globalInterfaceTypes, isUpdate);
72 if (validateAllowedOperationCountOnLocalInterfaceType.isRight()) {
73 return validateAllowedOperationCountOnLocalInterfaceType;
76 Either<Boolean, ResponseFormat> validateAllowedOperationsOnGlobalInterfaceType =
77 validateAllowedOperationsOnGlobalInterfaceType(inputInterfaceDefinition, globalInterfaceTypes);
78 if (validateAllowedOperationsOnGlobalInterfaceType.isRight()) {
79 return validateAllowedOperationsOnGlobalInterfaceType;
82 Either<Boolean, ResponseFormat> validateOperationNameUniqueness =
83 validateOperationNameUniquenessInCollection(inputInterfaceDefinition.getOperationsMap().values());
84 if (validateOperationNameUniqueness.isRight()) {
85 return validateOperationNameUniqueness;
88 for (Operation interfaceOperation : inputInterfaceDefinition.getOperationsMap().values()) {
89 Either<Boolean, ResponseFormat> interfaceOperationValidatorResponse = validateInterfaceOperation(
90 interfaceOperation, storedInterfaceDefinition, inputInterfaceDefinition, component, isUpdate);
91 if (interfaceOperationValidatorResponse.isRight()) {
92 return interfaceOperationValidatorResponse;
96 return Either.left(Boolean.TRUE);
99 public Either<Boolean, ResponseFormat> validateDeleteOperationContainsNoMappedOutput(
100 Operation interfaceOperationToDelete, org.openecomp.sdc.be.model.Component component,
101 InterfaceDefinition storedInterfaceDefinition) {
102 ResponseFormatManager responseFormatManager = getResponseFormatManager();
103 List<OperationOutputDefinition> existingOperationOutputs =
104 getInterfaceOperationOutputs(interfaceOperationToDelete.getUniqueId(), component.getInterfaces());
105 if (existingOperationOutputs.isEmpty()) {
106 return Either.left(Boolean.TRUE);
108 String mappedOutputPrefix = storedInterfaceDefinition.getType() + "." + interfaceOperationToDelete.getName();
109 List<OperationInputDefinition> interfaceOperationInputs =
110 getOtherOperationInputsOfComponent(mappedOutputPrefix, component.getInterfaces());
111 Set<String> mappedOutputsInDeletedOperation = new HashSet<>();
112 Set<String> existingOperationOutputNames = existingOperationOutputs.stream()
113 .map(OperationOutputDefinition::getName)
114 .collect(Collectors.toSet());
115 for (String existingOperationOutputName : existingOperationOutputNames) {
116 Set<String> matchedOutputsMappedToInputs = interfaceOperationInputs.stream()
117 .filter(operationInputDefinition -> operationInputDefinition.getInputId()
118 .equals(mappedOutputPrefix + "." + existingOperationOutputName))
119 .map(operationInputDefinition -> getOperationOutputName(operationInputDefinition.getInputId()))
120 .collect(Collectors.toSet());
121 mappedOutputsInDeletedOperation.addAll(matchedOutputsMappedToInputs);
124 if (CollectionUtils.isNotEmpty(mappedOutputsInDeletedOperation)) {
125 return getMappedOutputErrorResponse(responseFormatManager, mappedOutputsInDeletedOperation,
126 "Cannot delete interface operation with output(s) '{}' mapped to another operation input",
127 ActionStatus.INTERFACE_OPERATION_DELETE_WITH_MAPPED_OUTPUT);
129 return Either.left(Boolean.TRUE);
132 private Either<Boolean, ResponseFormat> validateAllowedOperationCountOnLocalInterfaceType(
133 InterfaceDefinition inputInterfaceDefinition, InterfaceDefinition storedInterfaceDefinition,
134 Map<String, InterfaceDefinition> globalInterfaceTypes, boolean isUpdate) {
136 boolean isInterfaceTypeExistInGlobalType =
137 globalInterfaceTypes.values().stream().map(InterfaceDefinition::getType)
138 .anyMatch(type -> type.equalsIgnoreCase(inputInterfaceDefinition.getType()));
139 if (!isInterfaceTypeExistInGlobalType
140 && isValidOperationOnLocalInterfaceType(inputInterfaceDefinition, storedInterfaceDefinition,
142 return Either.right(getResponseFormatManager()
143 .getResponseFormat(ActionStatus.INTERFACE_OPERATION_INVALID_FOR_LOCAL_TYPE,
144 inputInterfaceDefinition.getType()));
147 return Either.left(Boolean.TRUE);
150 private boolean isValidOperationOnLocalInterfaceType(InterfaceDefinition inputInterfaceDefinition,
151 InterfaceDefinition storedInterfaceDefinition,
153 return inputInterfaceDefinition.getOperations().size() > 1
154 || (!isUpdate && storedInterfaceDefinition != null
155 && storedInterfaceDefinition.getType()
156 .equalsIgnoreCase(inputInterfaceDefinition.getType()));
159 private Either<Boolean, ResponseFormat> validateAllowedOperationsOnGlobalInterfaceType(
160 InterfaceDefinition interfaceDefinition, Map<String, InterfaceDefinition> globalInterfaceTypes) {
162 if (globalInterfaceTypes == null) {
163 return Either.left(Boolean.TRUE);
165 boolean isOperationValidOnGlobalInterfaceType = Stream.of(interfaceDefinition)
166 .filter(interfaceDef -> globalInterfaceTypes.values().stream().anyMatch(interfaceDef1 ->
167 interfaceDef1.getType().equalsIgnoreCase(interfaceDef.getType())))
168 .flatMap(interfaceDef -> interfaceDef.getOperationsMap().values().stream().map(Operation::getName))
169 .allMatch(operationName -> globalInterfaceTypes.values().stream()
170 .flatMap(interfaceDef -> interfaceDef.getOperationsMap().keySet().stream())
171 .anyMatch(opName -> opName.equalsIgnoreCase(operationName)));
172 if (!isOperationValidOnGlobalInterfaceType) {
173 return Either.right(getResponseFormatManager()
174 .getResponseFormat(ActionStatus.INTERFACE_OPERATION_INVALID_FOR_GLOBAL_TYPE,
175 interfaceDefinition.getType()));
177 return Either.left(Boolean.TRUE);
180 private Either<Boolean, ResponseFormat> validateOperationNameUniquenessInCollection(
181 Collection<Operation> operationList) {
182 HashSet<String> operationNames = new HashSet<>();
183 for (Operation operation : operationList) {
184 if (!operationNames.add(operation.getName())) {
185 return Either.right(getResponseFormatManager()
186 .getResponseFormat(ActionStatus.INTERFACE_OPERATION_NAME_ALREADY_IN_USE,
187 operation.getName()));
190 return Either.left(Boolean.TRUE);
193 private Either<Boolean, ResponseFormat> validateInterfaceOperation(Operation interfaceOperation,
194 InterfaceDefinition storedInterfaceDefinition, InterfaceDefinition inputInterfaceDefinition,
195 org.openecomp.sdc.be.model.Component component, boolean isUpdate) {
197 ResponseFormatManager responseFormatManager = getResponseFormatManager();
198 Either<Boolean, ResponseFormat> interfaceOperationTypeResponse =
199 isInterfaceOperationTypeValid(interfaceOperation, responseFormatManager, storedInterfaceDefinition,
201 if (interfaceOperationTypeResponse.isRight()) {
202 return Either.right(interfaceOperationTypeResponse.right().value());
205 if (null != interfaceOperation.getInputs()
206 && CollectionUtils.isNotEmpty(interfaceOperation.getInputs().getListToscaDataDefinition())) {
207 Either<Boolean, ResponseFormat> inputParametersResponse =
208 validateInputParameters(interfaceOperation, responseFormatManager);
209 if (inputParametersResponse.isRight()) {
210 return Either.right(inputParametersResponse.right().value());
213 Either<Boolean, ResponseFormat> inputPropertyExistInComponent =
214 validateInputPropertyExistInComponent(interfaceOperation,
215 inputInterfaceDefinition, component, responseFormatManager);
216 if (inputPropertyExistInComponent.isRight()) {
217 return Either.right(inputPropertyExistInComponent.right().value());
221 if (null != interfaceOperation.getOutputs()
222 && CollectionUtils.isNotEmpty(interfaceOperation.getOutputs().getListToscaDataDefinition())) {
223 Either<Boolean, ResponseFormat> outputParametersResponse =
224 validateOutputParameters(interfaceOperation, responseFormatManager);
225 if (outputParametersResponse.isRight()) {
226 return Either.right(outputParametersResponse.right().value());
230 if (MapUtils.isNotEmpty(component.getInterfaces()) && isUpdate) {
231 Either<Boolean, ResponseFormat> mappedOutputModifiedResponse =
232 validateMappedOutputNotModified(interfaceOperation, component, inputInterfaceDefinition,
233 responseFormatManager);
234 if (mappedOutputModifiedResponse.isRight()) {
235 return Either.right(mappedOutputModifiedResponse.right().value());
239 return Either.left(Boolean.TRUE);
243 private Either<Boolean, ResponseFormat> validateMappedOutputNotModified(Operation interfaceOperation,
244 org.openecomp.sdc.be.model.Component component, InterfaceDefinition interfaceDefinition,
245 ResponseFormatManager responseFormatManager) {
247 List<OperationOutputDefinition> existingOperationOutputs =
248 getInterfaceOperationOutputs(interfaceOperation.getUniqueId(), component.getInterfaces());
249 if (existingOperationOutputs.isEmpty()) {
250 return Either.left(Boolean.TRUE);
252 Set<String> existingOperationOutputNames = existingOperationOutputs.stream()
253 .map(OperationOutputDefinition::getName)
254 .collect(Collectors.toSet());
256 ListDataDefinition<OperationOutputDefinition> currentOutputs = interfaceOperation.getOutputs();
257 Set<String> currentOperationOutputNames = new HashSet<>();
258 if (currentOutputs != null && !currentOutputs.isEmpty()) {
259 currentOperationOutputNames = currentOutputs.getListToscaDataDefinition().stream()
260 .map(OperationOutputDefinition::getName)
261 .collect(Collectors.toSet());
263 String mappedOutputPrefix = interfaceDefinition.getType() + "." + interfaceOperation.getName();
264 //Get the deleted outputs (name changed also equivalent to deleted)
265 Set<String> deletedOutputs = Sets.difference(existingOperationOutputNames, currentOperationOutputNames);
266 Set<String> deletedMappedOutputs = getModifiedMappedOutputs(deletedOutputs, mappedOutputPrefix,
267 component.getInterfaces());
269 if (CollectionUtils.isNotEmpty(deletedMappedOutputs)) {
270 return getMappedOutputErrorResponse(responseFormatManager, deletedMappedOutputs,
271 "Cannot update or delete interface operation output(s) '{}' mapped to an operation input",
272 ActionStatus.INTERFACE_OPERATION_MAPPED_OUTPUT_MODIFIED);
275 if (currentOutputs != null && !currentOutputs.isEmpty()) {
276 //Get the unchanged outputs based on name to see if other attributes (type/mandatory) have not been changed
277 Set<String> unchangedOutputNames = Sets.intersection(existingOperationOutputNames,
278 currentOperationOutputNames);
279 Set<String> modifiedOutputNames =
280 getModifiedOutputNames(currentOutputs.getListToscaDataDefinition(),
281 existingOperationOutputs, unchangedOutputNames);
282 Set<String> modifiedMappedOutputNames = getModifiedMappedOutputs(modifiedOutputNames, mappedOutputPrefix,
283 component.getInterfaces());
284 if (CollectionUtils.isNotEmpty(modifiedMappedOutputNames)) {
285 return getMappedOutputErrorResponse(responseFormatManager, modifiedMappedOutputNames,
286 "Cannot update or delete interface operation output(s) '{}' mapped to an operation input",
287 ActionStatus.INTERFACE_OPERATION_MAPPED_OUTPUT_MODIFIED);
291 return Either.left(Boolean.TRUE);
294 private Set<String> getModifiedMappedOutputs(Set<String> modifiedOutputNames, String mappedOutputPrefix,
295 Map<String, InterfaceDefinition> componentInterfaces) {
296 return modifiedOutputNames.stream()
297 .filter(modifiedOutputName -> isMappedOutputModified(mappedOutputPrefix, modifiedOutputName,
298 componentInterfaces))
299 .map(InterfaceOperationUtils::getOperationOutputName)
300 .collect(Collectors.toSet());
303 private boolean isMappedOutputModified(String mappedOutputPrefix, String outputName,
304 Map<String, InterfaceDefinition> componentInterfaces) {
305 List<OperationInputDefinition> interfaceOperationInputs =
306 getOtherOperationInputsOfComponent(mappedOutputPrefix, componentInterfaces);
307 return interfaceOperationInputs.stream()
308 .anyMatch(operationInputDefinition -> operationInputDefinition.getInputId()
309 .equals(mappedOutputPrefix + "." + outputName));
312 private static Set<String> getModifiedOutputNames(List<OperationOutputDefinition> currentOperationOutputs,
313 List<OperationOutputDefinition> existingOperationOutputs,
314 Set<String> unchangedOutputNames) {
315 Set<String> modifiedOutputDefinitionNames = new HashSet<>();
316 Map<String, OperationOutputDefinition> newOutputMap = currentOperationOutputs.stream()
317 .collect(Collectors.toMap(OperationOutputDefinition::getName,
318 (OperationOutputDefinition operationOutputDefinition) -> operationOutputDefinition));
320 Map<String, OperationOutputDefinition> existingOutputMap = existingOperationOutputs.stream()
321 .collect(Collectors.toMap(OperationOutputDefinition::getName,
322 (OperationOutputDefinition operationOutputDefinition) -> operationOutputDefinition));
324 for (String outputName : unchangedOutputNames) {
325 OperationOutputDefinition existingOutputDefinition = existingOutputMap.get(outputName);
326 OperationOutputDefinition newOutputDefinition = newOutputMap.get(outputName);
327 if (!existingOutputDefinition.getType().equals(newOutputDefinition.getType())
328 || !existingOutputDefinition.isRequired().equals(newOutputDefinition.isRequired())) {
329 modifiedOutputDefinitionNames.add(outputName);
332 return modifiedOutputDefinitionNames;
335 private Either<Boolean, ResponseFormat> getMappedOutputErrorResponse(ResponseFormatManager responseFormatManager,
336 Set<String> modifiedMappedOutputs,
338 ActionStatus errorStatus) {
339 String modifiedOutputNameList = String.join(",", modifiedMappedOutputs);
340 LOGGER.error(message, modifiedOutputNameList);
341 ResponseFormat errorResponse = responseFormatManager.getResponseFormat(errorStatus, modifiedOutputNameList);
342 return Either.right(errorResponse);
346 protected ResponseFormatManager getResponseFormatManager() {
347 return ResponseFormatManager.getInstance();
350 private Either<Boolean, ResponseFormat> isInterfaceOperationTypeValid(Operation interfaceOperation,
351 ResponseFormatManager responseFormatManager,
352 InterfaceDefinition interfaceDefinition,
355 Either<Boolean, ResponseFormat> operationTypeEmptyEither =
356 isOperationTypeEmpty(responseFormatManager, interfaceOperation.getName());
357 if (operationTypeEmptyEither.isRight()) {
358 return Either.right(operationTypeEmptyEither.right().value());
361 Either<Boolean, ResponseFormat> operationTypeRegexValidationResponse =
362 isOperationTypeRegexValid(responseFormatManager, interfaceOperation.getName());
363 if (operationTypeRegexValidationResponse.isRight()) {
364 return Either.right(operationTypeRegexValidationResponse.right().value());
367 Either<Boolean, ResponseFormat> operationTypeUniqueResponse = validateOperationTypeUnique(interfaceOperation,
368 interfaceDefinition, isUpdate);
369 if (operationTypeUniqueResponse.isRight()) {
370 return Either.right(operationTypeUniqueResponse.right().value());
372 if (!operationTypeUniqueResponse.left().value()) {
373 LOGGER.error("Interface Operation type {} already in use ", interfaceOperation.getName());
374 ResponseFormat errorResponse = responseFormatManager.getResponseFormat(
375 ActionStatus.INTERFACE_OPERATION_NAME_ALREADY_IN_USE, interfaceOperation.getName());
376 return Either.right(errorResponse);
378 return Either.left(Boolean.TRUE);
381 private Either<Boolean, ResponseFormat> validateInputParameters(Operation interfaceOperation,
382 ResponseFormatManager responseFormatManager) {
383 if (isInputParameterNameEmpty(interfaceOperation)) {
384 LOGGER.error("Interface operation input parameter name can't be empty");
385 ResponseFormat inputResponse =
386 responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_INPUT_NAME_MANDATORY);
387 return Either.right(inputResponse);
390 Either<Boolean, Set<String>> validateInputParametersUniqueResponse =
391 isInputParametersUnique(interfaceOperation);
392 if (validateInputParametersUniqueResponse.isRight()) {
393 LOGGER.error("Interface operation input parameter names {} already in use",
394 validateInputParametersUniqueResponse.right().value());
395 ResponseFormat inputResponse =
396 responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_INPUT_NAME_ALREADY_IN_USE,
397 validateInputParametersUniqueResponse.right().value().toString());
398 return Either.right(inputResponse);
400 return Either.left(Boolean.TRUE);
403 private Either<Boolean, ResponseFormat> validateOutputParameters(Operation interfaceOperation,
404 ResponseFormatManager responseFormatManager) {
405 if (isOutputParameterNameEmpty(interfaceOperation)) {
406 LOGGER.error("Interface operation output parameter name can't be empty");
407 ResponseFormat inputResponse =
408 responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_OUTPUT_NAME_MANDATORY);
409 return Either.right(inputResponse);
412 Either<Boolean, Set<String>> validateOutputParametersUniqueResponse =
413 isOutputParametersUnique(interfaceOperation);
414 if (validateOutputParametersUniqueResponse.isRight()) {
415 LOGGER.error("Interface operation output parameter names {} already in use",
416 validateOutputParametersUniqueResponse.right().value());
417 ResponseFormat inputResponse =
418 responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_OUTPUT_NAME_ALREADY_IN_USE,
419 validateOutputParametersUniqueResponse.right().value().toString());
420 return Either.right(inputResponse);
422 return Either.left(Boolean.TRUE);
425 private Either<Boolean, ResponseFormat> isOperationTypeEmpty(ResponseFormatManager responseFormatManager,
426 String operationType) {
427 if (StringUtils.isEmpty(operationType)) {
428 LOGGER.error("Interface Operation type is mandatory");
429 ResponseFormat errorResponse =
430 responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NAME_MANDATORY);
431 return Either.right(errorResponse);
433 return Either.left(Boolean.TRUE);
436 private Either<Boolean, ResponseFormat> isOperationTypeRegexValid(ResponseFormatManager responseFormatManager,
437 String operationType) {
438 if (!isValidOperationType(operationType)) {
439 LOGGER.error("Interface Operation type {} is invalid, Operation type should not contain"
440 + "Special character, space, numbers and should not be greater than 200 characters",
442 ResponseFormat errorResponse = responseFormatManager
443 .getResponseFormat(ActionStatus.INTERFACE_OPERATION_NAME_INVALID,
445 return Either.right(errorResponse);
447 return Either.left(Boolean.TRUE);
450 private Either<Boolean, ResponseFormat> validateOperationTypeUnique(Operation interfaceOperation,
451 InterfaceDefinition interfaceDefinition, boolean isUpdate) {
452 boolean isOperationTypeUnique = false;
454 if (interfaceDefinition == null || CollectionUtils.isEmpty(interfaceDefinition.getOperationsMap().values())) {
455 return Either.left(true);
458 Map<String, String> operationTypes = new HashMap<>();
459 interfaceDefinition.getOperationsMap().values()
460 .forEach(operationType -> operationTypes.put(operationType.getUniqueId(), operationType.getName()));
462 if (!operationTypes.values().contains(interfaceOperation.getName())) {
463 isOperationTypeUnique = true;
465 if (!isOperationTypeUnique && isUpdate) {
466 Optional<String> id = operationTypes.entrySet().stream().filter(entry -> Objects.equals(entry.getValue(),
467 interfaceOperation.getName())).map(Map.Entry::getKey).findAny();
468 if (id.isPresent() && id.get().equalsIgnoreCase(interfaceOperation.getUniqueId())) {
469 isOperationTypeUnique = true;
473 return Either.left(isOperationTypeUnique);
476 private Boolean isInputParameterNameEmpty(Operation operationDataDefinition) {
477 return operationDataDefinition.getInputs().getListToscaDataDefinition().stream().anyMatch(
478 inputParam -> inputParam.getName() == null || inputParam.getName().trim().equals(StringUtils.EMPTY));
482 private Either<Boolean, Set<String>> isInputParametersUnique(Operation operationDataDefinition) {
483 Set<String> inputParamNamesSet = new HashSet<>();
484 Set<String> duplicateParamNamesToReturn = new HashSet<>();
485 operationDataDefinition.getInputs().getListToscaDataDefinition()
486 .forEach(inputParam -> {
487 if (!inputParamNamesSet.add(inputParam.getName().trim())) {
488 duplicateParamNamesToReturn.add(inputParam.getName().trim());
491 if (!duplicateParamNamesToReturn.isEmpty()) {
492 return Either.right(duplicateParamNamesToReturn);
494 return Either.left(Boolean.TRUE);
497 private Boolean isOutputParameterNameEmpty(Operation operationDataDefinition) {
498 return operationDataDefinition.getOutputs().getListToscaDataDefinition().stream().anyMatch(
499 outputParam -> outputParam.getName() == null || outputParam.getName().trim().equals(StringUtils.EMPTY));
502 private Either<Boolean, Set<String>> isOutputParametersUnique(Operation operationDataDefinition) {
503 Set<String> outputParamNamesSet = new HashSet<>();
504 Set<String> duplicateParamNamesToReturn = new HashSet<>();
505 operationDataDefinition.getOutputs().getListToscaDataDefinition()
506 .forEach(outputParam -> {
507 if (!outputParamNamesSet.add(outputParam.getName().trim())) {
508 duplicateParamNamesToReturn.add(outputParam.getName().trim());
511 if (!duplicateParamNamesToReturn.isEmpty()) {
512 return Either.right(duplicateParamNamesToReturn);
514 return Either.left(Boolean.TRUE);
517 private Either<Boolean, ResponseFormat> validateInputPropertyExistInComponent(Operation operation,
518 InterfaceDefinition inputInterfaceDefinition, org.openecomp.sdc.be.model.Component component,
519 ResponseFormatManager responseFormatManager) {
521 boolean isOperationInputToInputPropertyMappingValid = false;
522 boolean isOperationInputToOtherOperationOutputMappingValid = false;
523 String mappingName = "";
524 List<OperationInputDefinition> inputListToscaDataDefinition =
525 operation.getInputs().getListToscaDataDefinition();
526 for (OperationInputDefinition inputDefinition : inputListToscaDataDefinition) {
527 if (isOperationInputMappedToComponentInput(inputDefinition, component.getInputs())
528 || isCapabilityProperty(inputDefinition.getInputId(), component).isPresent()) {
529 isOperationInputToInputPropertyMappingValid = true;
531 mappingName = inputDefinition.getInputId().contains(".")
532 ? inputDefinition.getInputId().substring(inputDefinition.getInputId().lastIndexOf('.') + 1)
533 : inputDefinition.getInputId();
537 if (isOperationInputToInputPropertyMappingValid) {
538 return Either.left(Boolean.TRUE);
541 //Mapped property not found in the component properties.. Check in other operation output parameters of
542 // component (other operation => not having the same full name)
543 String actualOperationIdentifier = inputInterfaceDefinition.getType() + "." + operation.getName();
544 ListDataDefinition<OperationOutputDefinition> outputListDataDefinition =
545 getOtherOperationOutputsOfComponent(actualOperationIdentifier, component.getInterfaces());
547 List<OperationOutputDefinition> componentOutputsFromOtherOperations =
548 outputListDataDefinition.getListToscaDataDefinition();
549 if (validateOutputExistsInComponent(mappingName, componentOutputsFromOtherOperations)) {
550 isOperationInputToOtherOperationOutputMappingValid = true;
552 //Get the output parameter display name from the full name
553 mappingName = getOperationOutputName(mappingName);
556 if (!isOperationInputToOtherOperationOutputMappingValid) {
557 LOGGER.error("Interface operation input parameter property {} not found in component input properties or"
558 + "capability properties or outputs of other operations.", mappingName);
559 ResponseFormat inputResponse = responseFormatManager
560 .getResponseFormat(ActionStatus.INTERFACE_OPERATION_INPUT_PROPERTY_NOT_FOUND_IN_COMPONENT,
561 mappingName, component.getComponentType().getValue());
562 return Either.right(inputResponse);
564 return Either.left(Boolean.TRUE);
567 private boolean validateOutputExistsInComponent(String mappedOutputName,
568 List<OperationOutputDefinition> outputs) {
569 return outputs.stream()
570 .anyMatch(output -> output.getName().equals(mappedOutputName));
574 * Get the input definitions of other operations of the component from current as well as other interfaces.
575 * @param currentOperationIdentifier Identifier for the request operation (interface_name.operation_name)
576 * @param componentInterfaces Interfaces of the component
578 private List<OperationInputDefinition> getOtherOperationInputsOfComponent(String currentOperationIdentifier,
579 Map<String, InterfaceDefinition>
580 componentInterfaces) {
581 List<OperationInputDefinition> otherOperationInputs = new ArrayList<>();
582 if (MapUtils.isEmpty(componentInterfaces)) {
583 return otherOperationInputs;
585 for (Map.Entry<String, InterfaceDefinition> interfaceDefinitionEntry : componentInterfaces.entrySet()) {
586 final Map<String, OperationDataDefinition> operations = interfaceDefinitionEntry.getValue().getOperations();
587 if (MapUtils.isEmpty(operations)) {
590 for (Map.Entry<String, OperationDataDefinition> operationEntry : operations.entrySet()) {
591 ListDataDefinition<OperationInputDefinition> inputs = operationEntry.getValue().getInputs();
592 String expectedOperationIdentifier =
593 interfaceDefinitionEntry.getValue().getType() + "." + operationEntry.getValue().getName();
594 if (!currentOperationIdentifier.equals(expectedOperationIdentifier) && Objects.nonNull(inputs) && !inputs.isEmpty()) {
595 otherOperationInputs.addAll(inputs.getListToscaDataDefinition());
599 return otherOperationInputs;
603 * Get the output of an operation in an interface.
604 * @param inputOperationId Unique identifier for the request operation
605 * @param componentInterfaces Interfaces of the component
607 private List<OperationOutputDefinition> getInterfaceOperationOutputs(String inputOperationId,
608 Map<String, InterfaceDefinition>
609 componentInterfaces) {
610 List<OperationOutputDefinition> operationOutputDefinitions = new ArrayList<>();
611 if (MapUtils.isEmpty(componentInterfaces)) {
612 return operationOutputDefinitions;
614 for (Map.Entry<String, InterfaceDefinition> interfaceDefinitionEntry : componentInterfaces.entrySet()) {
615 final Map<String, OperationDataDefinition> operations = interfaceDefinitionEntry.getValue().getOperations();
616 if (MapUtils.isEmpty(operations)) {
619 for (Map.Entry<String, OperationDataDefinition> operationEntry : operations.entrySet()) {
620 String expectedOperationId = operationEntry.getValue().getUniqueId();
621 if (expectedOperationId.equals(inputOperationId)) {
622 ListDataDefinition<OperationOutputDefinition> operationOutputs =
623 operationEntry.getValue().getOutputs();
624 return (Objects.isNull(operationOutputs) || operationOutputs.isEmpty())
625 ? operationOutputDefinitions
626 : operationOutputs.getListToscaDataDefinition();
630 return operationOutputDefinitions;
633 private boolean isValidOperationType(String operationType) {
634 return Pattern.matches(TYPE_VALIDATION_REGEX, operationType);