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 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;
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;
44 import java.util.Objects;
45 import java.util.Optional;
47 import java.util.regex.Pattern;
48 import java.util.stream.Collectors;
49 import java.util.stream.Stream;
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;
56 @Component("interfaceOperationValidation")
57 public class InterfaceOperationValidation {
59 private static final String TYPE_VALIDATION_REGEX = "^[a-zA-Z0-9_]{1,200}$";
61 private static final Logger LOGGER = LoggerFactory.getLogger(InterfaceOperationValidation.class);
63 public Either<Boolean, ResponseFormat> validateInterfaceOperations(
64 InterfaceDefinition inputInterfaceDefinition, org.openecomp.sdc.be.model.Component component,
65 InterfaceDefinition storedInterfaceDefinition, Map<String, InterfaceDefinition> globalInterfaceTypes,
68 Either<Boolean, ResponseFormat> validateAllowedOperationsOnGlobalInterfaceType =
69 validateAllowedOperationsOnGlobalInterfaceType(inputInterfaceDefinition, globalInterfaceTypes);
70 if (validateAllowedOperationsOnGlobalInterfaceType.isRight()) {
71 return validateAllowedOperationsOnGlobalInterfaceType;
74 Either<Boolean, ResponseFormat> validateOperationNameUniqueness =
75 validateOperationNameUniquenessInCollection(inputInterfaceDefinition.getOperationsMap().values());
76 if (validateOperationNameUniqueness.isRight()) {
77 return validateOperationNameUniqueness;
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;
88 return Either.left(Boolean.TRUE);
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);
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);
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);
121 return Either.left(Boolean.TRUE);
124 private Either<Boolean, ResponseFormat> validateAllowedOperationCountOnLocalInterfaceType(
125 InterfaceDefinition inputInterfaceDefinition, InterfaceDefinition storedInterfaceDefinition,
126 Map<String, InterfaceDefinition> globalInterfaceTypes, boolean isUpdate) {
128 boolean isInterfaceTypeExistInGlobalType =
129 globalInterfaceTypes.values().stream().map(InterfaceDefinition::getType)
130 .anyMatch(type -> type.equalsIgnoreCase(inputInterfaceDefinition.getType()));
131 if (!isInterfaceTypeExistInGlobalType
132 && isValidOperationOnLocalInterfaceType(inputInterfaceDefinition, storedInterfaceDefinition,
134 return Either.right(getResponseFormatManager()
135 .getResponseFormat(ActionStatus.INTERFACE_OPERATION_INVALID_FOR_LOCAL_TYPE,
136 inputInterfaceDefinition.getType()));
139 return Either.left(Boolean.TRUE);
142 private boolean isValidOperationOnLocalInterfaceType(InterfaceDefinition inputInterfaceDefinition,
143 InterfaceDefinition storedInterfaceDefinition,
145 return inputInterfaceDefinition.getOperations().size() > 1
146 || (!isUpdate && storedInterfaceDefinition != null
147 && storedInterfaceDefinition.getType()
148 .equalsIgnoreCase(inputInterfaceDefinition.getType()));
151 private Either<Boolean, ResponseFormat> validateAllowedOperationsOnGlobalInterfaceType(
152 InterfaceDefinition interfaceDefinition, Map<String, InterfaceDefinition> globalInterfaceTypes) {
154 if (globalInterfaceTypes == null) {
155 return Either.left(Boolean.TRUE);
157 boolean isOperationValidOnGlobalInterfaceType = Stream.of(interfaceDefinition)
158 .filter(interfaceDef -> globalInterfaceTypes.values().stream().anyMatch(interfaceDef1 ->
159 interfaceDef1.getType().equalsIgnoreCase(interfaceDef.getType())))
160 .flatMap(interfaceDef -> interfaceDef.getOperationsMap().values().stream().map(Operation::getName))
161 .allMatch(operationName -> globalInterfaceTypes.values().stream()
162 .flatMap(interfaceDef -> interfaceDef.getOperationsMap().keySet().stream())
163 .anyMatch(opName -> opName.equalsIgnoreCase(operationName)));
164 if (!isOperationValidOnGlobalInterfaceType) {
165 return Either.right(getResponseFormatManager()
166 .getResponseFormat(ActionStatus.INTERFACE_OPERATION_INVALID_FOR_GLOBAL_TYPE,
167 interfaceDefinition.getType()));
169 return Either.left(Boolean.TRUE);
172 private Either<Boolean, ResponseFormat> validateOperationNameUniquenessInCollection(
173 Collection<Operation> operationList) {
174 HashSet<String> operationNames = new HashSet<>();
175 for (Operation operation : operationList) {
176 if (!operationNames.add(operation.getName())) {
177 return Either.right(getResponseFormatManager()
178 .getResponseFormat(ActionStatus.INTERFACE_OPERATION_NAME_ALREADY_IN_USE,
179 operation.getName()));
182 return Either.left(Boolean.TRUE);
185 private Either<Boolean, ResponseFormat> validateInterfaceOperation(Operation interfaceOperation,
186 InterfaceDefinition storedInterfaceDefinition, InterfaceDefinition inputInterfaceDefinition,
187 org.openecomp.sdc.be.model.Component component, boolean isUpdate) {
189 ResponseFormatManager responseFormatManager = getResponseFormatManager();
190 Either<Boolean, ResponseFormat> interfaceOperationTypeResponse =
191 isInterfaceOperationTypeValid(interfaceOperation, responseFormatManager, storedInterfaceDefinition,
193 if (interfaceOperationTypeResponse.isRight()) {
194 return Either.right(interfaceOperationTypeResponse.right().value());
197 if (null != interfaceOperation.getInputs()
198 && CollectionUtils.isNotEmpty(interfaceOperation.getInputs().getListToscaDataDefinition())) {
199 Either<Boolean, ResponseFormat> inputParametersResponse =
200 validateInputParameters(interfaceOperation, responseFormatManager);
201 if (inputParametersResponse.isRight()) {
202 return Either.right(inputParametersResponse.right().value());
205 Either<Boolean, ResponseFormat> inputPropertyExistInComponent =
206 validateInputPropertyExistInComponent(interfaceOperation,
207 inputInterfaceDefinition, component, responseFormatManager);
208 if (inputPropertyExistInComponent.isRight()) {
209 return Either.right(inputPropertyExistInComponent.right().value());
213 if (null != interfaceOperation.getOutputs()
214 && CollectionUtils.isNotEmpty(interfaceOperation.getOutputs().getListToscaDataDefinition())) {
215 Either<Boolean, ResponseFormat> outputParametersResponse =
216 validateOutputParameters(interfaceOperation, responseFormatManager);
217 if (outputParametersResponse.isRight()) {
218 return Either.right(outputParametersResponse.right().value());
222 if (MapUtils.isNotEmpty(component.getInterfaces()) && isUpdate) {
223 Either<Boolean, ResponseFormat> mappedOutputModifiedResponse =
224 validateMappedOutputNotModified(interfaceOperation, component, inputInterfaceDefinition,
225 responseFormatManager);
226 if (mappedOutputModifiedResponse.isRight()) {
227 return Either.right(mappedOutputModifiedResponse.right().value());
231 return Either.left(Boolean.TRUE);
235 private Either<Boolean, ResponseFormat> validateMappedOutputNotModified(Operation interfaceOperation,
236 org.openecomp.sdc.be.model.Component component, InterfaceDefinition interfaceDefinition,
237 ResponseFormatManager responseFormatManager) {
239 List<OperationOutputDefinition> existingOperationOutputs =
240 getInterfaceOperationOutputs(interfaceOperation.getUniqueId(), component.getInterfaces());
241 if (existingOperationOutputs.isEmpty()) {
242 return Either.left(Boolean.TRUE);
244 Set<String> existingOperationOutputNames = existingOperationOutputs.stream()
245 .map(OperationOutputDefinition::getName)
246 .collect(Collectors.toSet());
248 ListDataDefinition<OperationOutputDefinition> currentOutputs = interfaceOperation.getOutputs();
249 Set<String> currentOperationOutputNames = new HashSet<>();
250 if (currentOutputs != null && !currentOutputs.isEmpty()) {
251 currentOperationOutputNames = currentOutputs.getListToscaDataDefinition().stream()
252 .map(OperationOutputDefinition::getName)
253 .collect(Collectors.toSet());
255 String mappedOutputPrefix = interfaceDefinition.getType() + "." + interfaceOperation.getName();
256 //Get the deleted outputs (name changed also equivalent to deleted)
257 Set<String> deletedOutputs = Sets.difference(existingOperationOutputNames, currentOperationOutputNames);
258 Set<String> deletedMappedOutputs = getModifiedMappedOutputs(deletedOutputs, mappedOutputPrefix,
259 component.getInterfaces());
261 if (CollectionUtils.isNotEmpty(deletedMappedOutputs)) {
262 return getMappedOutputErrorResponse(responseFormatManager, deletedMappedOutputs,
263 "Cannot update or delete interface operation output(s) '{}' mapped to an operation input",
264 ActionStatus.INTERFACE_OPERATION_MAPPED_OUTPUT_MODIFIED);
267 if (currentOutputs != null && !currentOutputs.isEmpty()) {
268 //Get the unchanged outputs based on name to see if other attributes (type/mandatory) have not been changed
269 Set<String> unchangedOutputNames = Sets.intersection(existingOperationOutputNames,
270 currentOperationOutputNames);
271 Set<String> modifiedOutputNames =
272 getModifiedOutputNames(currentOutputs.getListToscaDataDefinition(),
273 existingOperationOutputs, unchangedOutputNames);
274 Set<String> modifiedMappedOutputNames = getModifiedMappedOutputs(modifiedOutputNames, mappedOutputPrefix,
275 component.getInterfaces());
276 if (CollectionUtils.isNotEmpty(modifiedMappedOutputNames)) {
277 return getMappedOutputErrorResponse(responseFormatManager, modifiedMappedOutputNames,
278 "Cannot update or delete interface operation output(s) '{}' mapped to an operation input",
279 ActionStatus.INTERFACE_OPERATION_MAPPED_OUTPUT_MODIFIED);
283 return Either.left(Boolean.TRUE);
286 private Set<String> getModifiedMappedOutputs(Set<String> modifiedOutputNames, String mappedOutputPrefix,
287 Map<String, InterfaceDefinition> componentInterfaces) {
288 return modifiedOutputNames.stream()
289 .filter(modifiedOutputName -> isMappedOutputModified(mappedOutputPrefix, modifiedOutputName,
290 componentInterfaces))
291 .map(InterfaceOperationUtils::getOperationOutputName)
292 .collect(Collectors.toSet());
295 private boolean isMappedOutputModified(String mappedOutputPrefix, String outputName,
296 Map<String, InterfaceDefinition> componentInterfaces) {
297 List<OperationInputDefinition> interfaceOperationInputs =
298 getOtherOperationInputsOfComponent(mappedOutputPrefix, componentInterfaces);
299 return interfaceOperationInputs.stream()
300 .anyMatch(operationInputDefinition -> operationInputDefinition.getInputId()
301 .equals(mappedOutputPrefix + "." + outputName));
304 private static Set<String> getModifiedOutputNames(List<OperationOutputDefinition> currentOperationOutputs,
305 List<OperationOutputDefinition> existingOperationOutputs,
306 Set<String> unchangedOutputNames) {
307 Set<String> modifiedOutputDefinitionNames = new HashSet<>();
308 Map<String, OperationOutputDefinition> newOutputMap = currentOperationOutputs.stream()
309 .collect(Collectors.toMap(OperationOutputDefinition::getName,
310 (OperationOutputDefinition operationOutputDefinition) -> operationOutputDefinition));
312 Map<String, OperationOutputDefinition> existingOutputMap = existingOperationOutputs.stream()
313 .collect(Collectors.toMap(OperationOutputDefinition::getName,
314 (OperationOutputDefinition operationOutputDefinition) -> operationOutputDefinition));
316 for (String outputName : unchangedOutputNames) {
317 OperationOutputDefinition existingOutputDefinition = existingOutputMap.get(outputName);
318 OperationOutputDefinition newOutputDefinition = newOutputMap.get(outputName);
319 if (!existingOutputDefinition.getType().equals(newOutputDefinition.getType())
320 || !existingOutputDefinition.isRequired().equals(newOutputDefinition.isRequired())) {
321 modifiedOutputDefinitionNames.add(outputName);
324 return modifiedOutputDefinitionNames;
327 private Either<Boolean, ResponseFormat> getMappedOutputErrorResponse(ResponseFormatManager responseFormatManager,
328 Set<String> modifiedMappedOutputs,
330 ActionStatus errorStatus) {
331 String modifiedOutputNameList = String.join(",", modifiedMappedOutputs);
332 LOGGER.error(message, modifiedOutputNameList);
333 ResponseFormat errorResponse = responseFormatManager.getResponseFormat(errorStatus, modifiedOutputNameList);
334 return Either.right(errorResponse);
338 protected ResponseFormatManager getResponseFormatManager() {
339 return ResponseFormatManager.getInstance();
342 private Either<Boolean, ResponseFormat> isInterfaceOperationTypeValid(Operation interfaceOperation,
343 ResponseFormatManager responseFormatManager,
344 InterfaceDefinition interfaceDefinition,
347 Either<Boolean, ResponseFormat> operationTypeEmptyEither =
348 isOperationTypeEmpty(responseFormatManager, interfaceOperation.getName());
349 if (operationTypeEmptyEither.isRight()) {
350 return Either.right(operationTypeEmptyEither.right().value());
353 Either<Boolean, ResponseFormat> operationTypeRegexValidationResponse =
354 isOperationTypeRegexValid(responseFormatManager, interfaceOperation.getName());
355 if (operationTypeRegexValidationResponse.isRight()) {
356 return Either.right(operationTypeRegexValidationResponse.right().value());
359 Either<Boolean, ResponseFormat> operationTypeUniqueResponse = validateOperationTypeUnique(interfaceOperation,
360 interfaceDefinition, isUpdate);
361 if (operationTypeUniqueResponse.isRight()) {
362 return Either.right(operationTypeUniqueResponse.right().value());
364 if (!operationTypeUniqueResponse.left().value()) {
365 LOGGER.error("Interface Operation type {} already in use ", interfaceOperation.getName());
366 ResponseFormat errorResponse = responseFormatManager.getResponseFormat(
367 ActionStatus.INTERFACE_OPERATION_NAME_ALREADY_IN_USE, interfaceOperation.getName());
368 return Either.right(errorResponse);
370 return Either.left(Boolean.TRUE);
373 private Either<Boolean, ResponseFormat> validateInputParameters(Operation interfaceOperation,
374 ResponseFormatManager responseFormatManager) {
375 if (isInputParameterNameEmpty(interfaceOperation)) {
376 LOGGER.error("Interface operation input parameter name can't be empty");
377 ResponseFormat inputResponse =
378 responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_INPUT_NAME_MANDATORY);
379 return Either.right(inputResponse);
382 Either<Boolean, Set<String>> validateInputParametersUniqueResponse =
383 isInputParametersUnique(interfaceOperation);
384 if (validateInputParametersUniqueResponse.isRight()) {
385 LOGGER.error("Interface operation input parameter names {} already in use",
386 validateInputParametersUniqueResponse.right().value());
387 ResponseFormat inputResponse =
388 responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_INPUT_NAME_ALREADY_IN_USE,
389 validateInputParametersUniqueResponse.right().value().toString());
390 return Either.right(inputResponse);
392 return Either.left(Boolean.TRUE);
395 private Either<Boolean, ResponseFormat> validateOutputParameters(Operation interfaceOperation,
396 ResponseFormatManager responseFormatManager) {
397 if (isOutputParameterNameEmpty(interfaceOperation)) {
398 LOGGER.error("Interface operation output parameter name can't be empty");
399 ResponseFormat inputResponse =
400 responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_OUTPUT_NAME_MANDATORY);
401 return Either.right(inputResponse);
404 Either<Boolean, Set<String>> validateOutputParametersUniqueResponse =
405 isOutputParametersUnique(interfaceOperation);
406 if (validateOutputParametersUniqueResponse.isRight()) {
407 LOGGER.error("Interface operation output parameter names {} already in use",
408 validateOutputParametersUniqueResponse.right().value());
409 ResponseFormat inputResponse =
410 responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_OUTPUT_NAME_ALREADY_IN_USE,
411 validateOutputParametersUniqueResponse.right().value().toString());
412 return Either.right(inputResponse);
414 return Either.left(Boolean.TRUE);
417 private Either<Boolean, ResponseFormat> isOperationTypeEmpty(ResponseFormatManager responseFormatManager,
418 String operationType) {
419 if (StringUtils.isEmpty(operationType)) {
420 LOGGER.error("Interface Operation type is mandatory");
421 ResponseFormat errorResponse =
422 responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NAME_MANDATORY);
423 return Either.right(errorResponse);
425 return Either.left(Boolean.TRUE);
428 private Either<Boolean, ResponseFormat> isOperationTypeRegexValid(ResponseFormatManager responseFormatManager,
429 String operationType) {
430 if (!isValidOperationType(operationType)) {
431 LOGGER.error("Interface Operation type {} is invalid, Operation type should not contain"
432 + "Special character, space, numbers and should not be greater than 200 characters",
434 ResponseFormat errorResponse = responseFormatManager
435 .getResponseFormat(ActionStatus.INTERFACE_OPERATION_NAME_INVALID,
437 return Either.right(errorResponse);
439 return Either.left(Boolean.TRUE);
442 private Either<Boolean, ResponseFormat> validateOperationTypeUnique(Operation interfaceOperation,
443 InterfaceDefinition interfaceDefinition, boolean isUpdate) {
444 boolean isOperationTypeUnique = false;
446 if (interfaceDefinition == null || CollectionUtils.isEmpty(interfaceDefinition.getOperationsMap().values())) {
447 return Either.left(true);
450 Map<String, String> operationTypes = new HashMap<>();
451 interfaceDefinition.getOperationsMap().values()
452 .forEach(operationType -> operationTypes.put(operationType.getUniqueId(), operationType.getName()));
454 if (!operationTypes.values().contains(interfaceOperation.getName())) {
455 isOperationTypeUnique = true;
457 if (!isOperationTypeUnique && isUpdate) {
458 Optional<String> id = operationTypes.entrySet().stream().filter(entry -> Objects.equals(entry.getValue(),
459 interfaceOperation.getName())).map(Map.Entry::getKey).findAny();
460 if (id.isPresent() && id.get().equalsIgnoreCase(interfaceOperation.getUniqueId())) {
461 isOperationTypeUnique = true;
465 return Either.left(isOperationTypeUnique);
468 private Boolean isInputParameterNameEmpty(Operation operationDataDefinition) {
469 return operationDataDefinition.getInputs().getListToscaDataDefinition().stream().anyMatch(
470 inputParam -> inputParam.getName() == null || inputParam.getName().trim().equals(StringUtils.EMPTY));
474 private Either<Boolean, Set<String>> isInputParametersUnique(Operation operationDataDefinition) {
475 Set<String> inputParamNamesSet = new HashSet<>();
476 Set<String> duplicateParamNamesToReturn = new HashSet<>();
477 operationDataDefinition.getInputs().getListToscaDataDefinition()
478 .forEach(inputParam -> {
479 if (!inputParamNamesSet.add(inputParam.getName().trim())) {
480 duplicateParamNamesToReturn.add(inputParam.getName().trim());
483 if (!duplicateParamNamesToReturn.isEmpty()) {
484 return Either.right(duplicateParamNamesToReturn);
486 return Either.left(Boolean.TRUE);
489 private Boolean isOutputParameterNameEmpty(Operation operationDataDefinition) {
490 return operationDataDefinition.getOutputs().getListToscaDataDefinition().stream().anyMatch(
491 outputParam -> outputParam.getName() == null || outputParam.getName().trim().equals(StringUtils.EMPTY));
494 private Either<Boolean, Set<String>> isOutputParametersUnique(Operation operationDataDefinition) {
495 Set<String> outputParamNamesSet = new HashSet<>();
496 Set<String> duplicateParamNamesToReturn = new HashSet<>();
497 operationDataDefinition.getOutputs().getListToscaDataDefinition()
498 .forEach(outputParam -> {
499 if (!outputParamNamesSet.add(outputParam.getName().trim())) {
500 duplicateParamNamesToReturn.add(outputParam.getName().trim());
503 if (!duplicateParamNamesToReturn.isEmpty()) {
504 return Either.right(duplicateParamNamesToReturn);
506 return Either.left(Boolean.TRUE);
509 private Either<Boolean, ResponseFormat> validateInputPropertyExistInComponent(Operation operation,
510 InterfaceDefinition inputInterfaceDefinition, org.openecomp.sdc.be.model.Component component,
511 ResponseFormatManager responseFormatManager) {
513 boolean isOperationInputToInputPropertyMappingValid = false;
514 boolean isOperationInputToOtherOperationOutputMappingValid = false;
515 String mappingName = "";
516 List<OperationInputDefinition> inputListToscaDataDefinition =
517 operation.getInputs().getListToscaDataDefinition();
518 for (OperationInputDefinition inputDefinition : inputListToscaDataDefinition) {
519 if (isOperationInputMappedToComponentInput(inputDefinition, component.getInputs())
520 || isCapabilityProperty(inputDefinition.getInputId(), component).isPresent()) {
521 isOperationInputToInputPropertyMappingValid = true;
523 mappingName = inputDefinition.getInputId().contains(".")
524 ? inputDefinition.getInputId().substring(inputDefinition.getInputId().lastIndexOf('.') + 1)
525 : inputDefinition.getInputId();
529 if (isOperationInputToInputPropertyMappingValid) {
530 return Either.left(Boolean.TRUE);
533 //Mapped property not found in the component properties.. Check in other operation output parameters of
534 // component (other operation => not having the same full name)
535 String actualOperationIdentifier = inputInterfaceDefinition.getType() + "." + operation.getName();
536 ListDataDefinition<OperationOutputDefinition> outputListDataDefinition =
537 getOtherOperationOutputsOfComponent(actualOperationIdentifier, component.getInterfaces());
539 List<OperationOutputDefinition> componentOutputsFromOtherOperations =
540 outputListDataDefinition.getListToscaDataDefinition();
541 if (validateOutputExistsInComponent(mappingName, componentOutputsFromOtherOperations)) {
542 isOperationInputToOtherOperationOutputMappingValid = true;
544 //Get the output parameter display name from the full name
545 mappingName = getOperationOutputName(mappingName);
548 if (!isOperationInputToOtherOperationOutputMappingValid) {
549 LOGGER.error("Interface operation input parameter property {} not found in component input properties or"
550 + "capability properties or outputs of other operations.", mappingName);
551 ResponseFormat inputResponse = responseFormatManager
552 .getResponseFormat(ActionStatus.INTERFACE_OPERATION_INPUT_PROPERTY_NOT_FOUND_IN_COMPONENT,
553 mappingName, component.getComponentType().getValue());
554 return Either.right(inputResponse);
556 return Either.left(Boolean.TRUE);
559 private boolean validateOutputExistsInComponent(String mappedOutputName,
560 List<OperationOutputDefinition> outputs) {
561 return outputs.stream()
562 .anyMatch(output -> output.getName().equals(mappedOutputName));
566 * Get the input definitions of other operations of the component from current as well as other interfaces.
567 * @param currentOperationIdentifier Identifier for the request operation (interface_name.operation_name)
568 * @param componentInterfaces Interfaces of the component
570 private List<OperationInputDefinition> getOtherOperationInputsOfComponent(String currentOperationIdentifier,
571 Map<String, InterfaceDefinition>
572 componentInterfaces) {
573 List<OperationInputDefinition> otherOperationInputs = new ArrayList<>();
574 if (MapUtils.isEmpty(componentInterfaces)) {
575 return otherOperationInputs;
577 for (Map.Entry<String, InterfaceDefinition> interfaceDefinitionEntry : componentInterfaces.entrySet()) {
578 final Map<String, OperationDataDefinition> operations = interfaceDefinitionEntry.getValue().getOperations();
579 if (MapUtils.isEmpty(operations)) {
582 for (Map.Entry<String, OperationDataDefinition> operationEntry : operations.entrySet()) {
583 ListDataDefinition<OperationInputDefinition> inputs = operationEntry.getValue().getInputs();
584 String expectedOperationIdentifier =
585 interfaceDefinitionEntry.getValue().getType() + "." + operationEntry.getValue().getName();
586 if (!currentOperationIdentifier.equals(expectedOperationIdentifier) && Objects.nonNull(inputs) && !inputs.isEmpty()) {
587 otherOperationInputs.addAll(inputs.getListToscaDataDefinition());
591 return otherOperationInputs;
595 * Get the output of an operation in an interface.
596 * @param inputOperationId Unique identifier for the request operation
597 * @param componentInterfaces Interfaces of the component
599 private List<OperationOutputDefinition> getInterfaceOperationOutputs(String inputOperationId,
600 Map<String, InterfaceDefinition>
601 componentInterfaces) {
602 List<OperationOutputDefinition> operationOutputDefinitions = new ArrayList<>();
603 if (MapUtils.isEmpty(componentInterfaces)) {
604 return operationOutputDefinitions;
606 for (Map.Entry<String, InterfaceDefinition> interfaceDefinitionEntry : componentInterfaces.entrySet()) {
607 final Map<String, OperationDataDefinition> operations = interfaceDefinitionEntry.getValue().getOperations();
608 if (MapUtils.isEmpty(operations)) {
611 for (Map.Entry<String, OperationDataDefinition> operationEntry : operations.entrySet()) {
612 String expectedOperationId = operationEntry.getValue().getUniqueId();
613 if (expectedOperationId.equals(inputOperationId)) {
614 ListDataDefinition<OperationOutputDefinition> operationOutputs =
615 operationEntry.getValue().getOutputs();
616 return (Objects.isNull(operationOutputs) || operationOutputs.isEmpty())
617 ? operationOutputDefinitions
618 : operationOutputs.getListToscaDataDefinition();
622 return operationOutputDefinitions;
625 private boolean isValidOperationType(String operationType) {
626 return Pattern.matches(TYPE_VALIDATION_REGEX, operationType);