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;
23 import com.google.common.collect.Sets;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.List;
31 import java.util.Objects;
32 import java.util.Optional;
34 import java.util.regex.Pattern;
35 import java.util.stream.Collectors;
36 import java.util.stream.Stream;
38 import fj.data.Either;
39 import org.apache.commons.collections.CollectionUtils;
40 import org.apache.commons.collections.MapUtils;
41 import org.apache.commons.lang.StringUtils;
42 import org.openecomp.sdc.be.components.impl.ResponseFormatManager;
43 import org.openecomp.sdc.be.components.utils.InterfaceOperationUtils;
44 import org.openecomp.sdc.be.dao.api.ActionStatus;
45 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
46 import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
47 import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
48 import org.openecomp.sdc.be.datatypes.elements.OperationOutputDefinition;
49 import org.openecomp.sdc.be.model.InterfaceDefinition;
50 import org.openecomp.sdc.be.model.Operation;
51 import org.openecomp.sdc.exception.ResponseFormat;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
54 import org.springframework.stereotype.Component;
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> validateAllowedOperationCountOnLocalInterfaceType =
69 validateAllowedOperationCountOnLocalInterfaceType(inputInterfaceDefinition, storedInterfaceDefinition,
70 globalInterfaceTypes, isUpdate);
71 if (validateAllowedOperationCountOnLocalInterfaceType.isRight()) {
72 return validateAllowedOperationCountOnLocalInterfaceType;
75 Either<Boolean, ResponseFormat> validateAllowedOperationsOnGlobalInterfaceType =
76 validateAllowedOperationsOnGlobalInterfaceType(inputInterfaceDefinition, globalInterfaceTypes);
77 if (validateAllowedOperationsOnGlobalInterfaceType.isRight()) {
78 return validateAllowedOperationsOnGlobalInterfaceType;
81 Either<Boolean, ResponseFormat> validateOperationNameUniqueness =
82 validateOperationNameUniquenessInCollection(inputInterfaceDefinition.getOperationsMap().values());
83 if (validateOperationNameUniqueness.isRight()) {
84 return validateOperationNameUniqueness;
87 for (Operation interfaceOperation : inputInterfaceDefinition.getOperationsMap().values()) {
88 Either<Boolean, ResponseFormat> interfaceOperationValidatorResponse = validateInterfaceOperation(
89 interfaceOperation, storedInterfaceDefinition, inputInterfaceDefinition, component, isUpdate);
90 if (interfaceOperationValidatorResponse.isRight()) {
91 return interfaceOperationValidatorResponse;
95 return Either.left(Boolean.TRUE);
98 public Either<Boolean, ResponseFormat> validateDeleteOperationContainsNoMappedOutput(
99 Operation interfaceOperationToDelete, org.openecomp.sdc.be.model.Component component,
100 InterfaceDefinition storedInterfaceDefinition) {
101 ResponseFormatManager responseFormatManager = getResponseFormatManager();
102 List<OperationOutputDefinition> existingOperationOutputs =
103 getInterfaceOperationOutputs(interfaceOperationToDelete.getUniqueId(), component.getInterfaces());
104 if (existingOperationOutputs.isEmpty()) {
105 return Either.left(Boolean.TRUE);
107 String mappedOutputPrefix = storedInterfaceDefinition.getType() + "." + interfaceOperationToDelete.getName();
108 List<OperationInputDefinition> interfaceOperationInputs =
109 getOtherOperationInputsOfComponent(mappedOutputPrefix, component.getInterfaces());
110 Set<String> mappedOutputsInDeletedOperation = new HashSet<>();
111 Set<String> existingOperationOutputNames = existingOperationOutputs.stream()
112 .map(OperationOutputDefinition::getName)
113 .collect(Collectors.toSet());
114 for (String existingOperationOutputName : existingOperationOutputNames) {
115 Set<String> matchedOutputsMappedToInputs = interfaceOperationInputs.stream()
116 .filter(operationInputDefinition -> operationInputDefinition.getInputId()
117 .equals(mappedOutputPrefix + "." + existingOperationOutputName))
118 .map(operationInputDefinition -> getOperationOutputName(operationInputDefinition.getInputId()))
119 .collect(Collectors.toSet());
120 mappedOutputsInDeletedOperation.addAll(matchedOutputsMappedToInputs);
123 if (CollectionUtils.isNotEmpty(mappedOutputsInDeletedOperation)) {
124 return getMappedOutputErrorResponse(responseFormatManager, mappedOutputsInDeletedOperation,
125 "Cannot delete interface operation with output(s) '{}' mapped to another operation input",
126 ActionStatus.INTERFACE_OPERATION_DELETE_WITH_MAPPED_OUTPUT);
128 return Either.left(Boolean.TRUE);
131 private Either<Boolean, ResponseFormat> validateAllowedOperationCountOnLocalInterfaceType(
132 InterfaceDefinition inputInterfaceDefinition, InterfaceDefinition storedInterfaceDefinition,
133 Map<String, InterfaceDefinition> globalInterfaceTypes, boolean isUpdate) {
135 boolean isInterfaceTypeExistInGlobalType =
136 globalInterfaceTypes.values().stream().map(InterfaceDefinition::getType)
137 .anyMatch(type -> type.equalsIgnoreCase(inputInterfaceDefinition.getType()));
138 if (!isInterfaceTypeExistInGlobalType
139 && isValidOperationOnLocalInterfaceType(inputInterfaceDefinition, storedInterfaceDefinition,
141 return Either.right(getResponseFormatManager()
142 .getResponseFormat(ActionStatus.INTERFACE_OPERATION_INVALID_FOR_LOCAL_TYPE,
143 inputInterfaceDefinition.getType()));
146 return Either.left(Boolean.TRUE);
149 private boolean isValidOperationOnLocalInterfaceType(InterfaceDefinition inputInterfaceDefinition,
150 InterfaceDefinition storedInterfaceDefinition,
152 return inputInterfaceDefinition.getOperations().size() > 1
153 || (!isUpdate && storedInterfaceDefinition != null
154 && storedInterfaceDefinition.getType()
155 .equalsIgnoreCase(inputInterfaceDefinition.getType()));
158 private Either<Boolean, ResponseFormat> validateAllowedOperationsOnGlobalInterfaceType(
159 InterfaceDefinition interfaceDefinition, Map<String, InterfaceDefinition> globalInterfaceTypes) {
161 if (globalInterfaceTypes == null) {
162 return Either.left(Boolean.TRUE);
164 boolean isOperationValidOnGlobalInterfaceType = Stream.of(interfaceDefinition)
165 .filter(interfaceDef -> globalInterfaceTypes.values().stream().anyMatch(interfaceDef1 ->
166 interfaceDef1.getType().equalsIgnoreCase(interfaceDef.getType())))
167 .flatMap(interfaceDef -> interfaceDef.getOperationsMap().values().stream().map(Operation::getName))
168 .allMatch(operationName -> globalInterfaceTypes.values().stream()
169 .flatMap(interfaceDef -> interfaceDef.getOperationsMap().keySet().stream())
170 .anyMatch(opName -> opName.equalsIgnoreCase(operationName)));
171 if (!isOperationValidOnGlobalInterfaceType) {
172 return Either.right(getResponseFormatManager()
173 .getResponseFormat(ActionStatus.INTERFACE_OPERATION_INVALID_FOR_GLOBAL_TYPE,
174 interfaceDefinition.getType()));
176 return Either.left(Boolean.TRUE);
179 private Either<Boolean, ResponseFormat> validateOperationNameUniquenessInCollection(
180 Collection<Operation> operationList) {
181 HashSet<String> operationNames = new HashSet<>();
182 for (Operation operation : operationList) {
183 if (!operationNames.add(operation.getName())) {
184 return Either.right(getResponseFormatManager()
185 .getResponseFormat(ActionStatus.INTERFACE_OPERATION_NAME_ALREADY_IN_USE,
186 operation.getName()));
189 return Either.left(Boolean.TRUE);
192 private Either<Boolean, ResponseFormat> validateInterfaceOperation(Operation interfaceOperation,
193 InterfaceDefinition storedInterfaceDefinition, InterfaceDefinition inputInterfaceDefinition,
194 org.openecomp.sdc.be.model.Component component, boolean isUpdate) {
196 ResponseFormatManager responseFormatManager = getResponseFormatManager();
197 Either<Boolean, ResponseFormat> interfaceOperationTypeResponse =
198 isInterfaceOperationTypeValid(interfaceOperation, responseFormatManager, storedInterfaceDefinition,
200 if (interfaceOperationTypeResponse.isRight()) {
201 return Either.right(interfaceOperationTypeResponse.right().value());
204 if (null != interfaceOperation.getInputs()
205 && CollectionUtils.isNotEmpty(interfaceOperation.getInputs().getListToscaDataDefinition())) {
206 Either<Boolean, ResponseFormat> inputParametersResponse =
207 validateInputParameters(interfaceOperation, responseFormatManager);
208 if (inputParametersResponse.isRight()) {
209 return Either.right(inputParametersResponse.right().value());
212 Either<Boolean, ResponseFormat> inputPropertyExistInComponent =
213 validateInputPropertyExistInComponent(interfaceOperation,
214 inputInterfaceDefinition, component, responseFormatManager);
215 if (inputPropertyExistInComponent.isRight()) {
216 return Either.right(inputPropertyExistInComponent.right().value());
220 if (null != interfaceOperation.getOutputs()
221 && CollectionUtils.isNotEmpty(interfaceOperation.getOutputs().getListToscaDataDefinition())) {
222 Either<Boolean, ResponseFormat> outputParametersResponse =
223 validateOutputParameters(interfaceOperation, responseFormatManager);
224 if (outputParametersResponse.isRight()) {
225 return Either.right(outputParametersResponse.right().value());
229 if (MapUtils.isNotEmpty(component.getInterfaces()) && isUpdate) {
230 Either<Boolean, ResponseFormat> mappedOutputModifiedResponse =
231 validateMappedOutputNotModified(interfaceOperation, component, inputInterfaceDefinition,
232 responseFormatManager);
233 if (mappedOutputModifiedResponse.isRight()) {
234 return Either.right(mappedOutputModifiedResponse.right().value());
238 return Either.left(Boolean.TRUE);
242 private Either<Boolean, ResponseFormat> validateMappedOutputNotModified(Operation interfaceOperation,
243 org.openecomp.sdc.be.model.Component component, InterfaceDefinition interfaceDefinition,
244 ResponseFormatManager responseFormatManager) {
246 List<OperationOutputDefinition> existingOperationOutputs =
247 getInterfaceOperationOutputs(interfaceOperation.getUniqueId(), component.getInterfaces());
248 if (existingOperationOutputs.isEmpty()) {
249 return Either.left(Boolean.TRUE);
251 Set<String> existingOperationOutputNames = existingOperationOutputs.stream()
252 .map(OperationOutputDefinition::getName)
253 .collect(Collectors.toSet());
255 ListDataDefinition<OperationOutputDefinition> currentOutputs = interfaceOperation.getOutputs();
256 Set<String> currentOperationOutputNames = new HashSet<>();
257 if (currentOutputs != null && !currentOutputs.isEmpty()) {
258 currentOperationOutputNames = currentOutputs.getListToscaDataDefinition().stream()
259 .map(OperationOutputDefinition::getName)
260 .collect(Collectors.toSet());
262 String mappedOutputPrefix = interfaceDefinition.getType() + "." + interfaceOperation.getName();
263 //Get the deleted outputs (name changed also equivalent to deleted)
264 Set<String> deletedOutputs = Sets.difference(existingOperationOutputNames, currentOperationOutputNames);
265 Set<String> deletedMappedOutputs = getModifiedMappedOutputs(deletedOutputs, mappedOutputPrefix,
266 component.getInterfaces());
268 if (CollectionUtils.isNotEmpty(deletedMappedOutputs)) {
269 return getMappedOutputErrorResponse(responseFormatManager, deletedMappedOutputs,
270 "Cannot update or delete interface operation output(s) '{}' mapped to an operation input",
271 ActionStatus.INTERFACE_OPERATION_MAPPED_OUTPUT_MODIFIED);
274 if (currentOutputs != null && !currentOutputs.isEmpty()) {
275 //Get the unchanged outputs based on name to see if other attributes (type/mandatory) have not been changed
276 Set<String> unchangedOutputNames = Sets.intersection(existingOperationOutputNames,
277 currentOperationOutputNames);
278 Set<String> modifiedOutputNames =
279 getModifiedOutputNames(currentOutputs.getListToscaDataDefinition(),
280 existingOperationOutputs, unchangedOutputNames);
281 Set<String> modifiedMappedOutputNames = getModifiedMappedOutputs(modifiedOutputNames, mappedOutputPrefix,
282 component.getInterfaces());
283 if (CollectionUtils.isNotEmpty(modifiedMappedOutputNames)) {
284 return getMappedOutputErrorResponse(responseFormatManager, modifiedMappedOutputNames,
285 "Cannot update or delete interface operation output(s) '{}' mapped to an operation input",
286 ActionStatus.INTERFACE_OPERATION_MAPPED_OUTPUT_MODIFIED);
290 return Either.left(Boolean.TRUE);
293 private Set<String> getModifiedMappedOutputs(Set<String> modifiedOutputNames, String mappedOutputPrefix,
294 Map<String, InterfaceDefinition> componentInterfaces) {
295 return modifiedOutputNames.stream()
296 .filter(modifiedOutputName -> isMappedOutputModified(mappedOutputPrefix, modifiedOutputName,
297 componentInterfaces))
298 .map(InterfaceOperationUtils::getOperationOutputName)
299 .collect(Collectors.toSet());
302 private boolean isMappedOutputModified(String mappedOutputPrefix, String outputName,
303 Map<String, InterfaceDefinition> componentInterfaces) {
304 List<OperationInputDefinition> interfaceOperationInputs =
305 getOtherOperationInputsOfComponent(mappedOutputPrefix, componentInterfaces);
306 return interfaceOperationInputs.stream()
307 .anyMatch(operationInputDefinition -> operationInputDefinition.getInputId()
308 .equals(mappedOutputPrefix + "." + outputName));
311 private static Set<String> getModifiedOutputNames(List<OperationOutputDefinition> currentOperationOutputs,
312 List<OperationOutputDefinition> existingOperationOutputs,
313 Set<String> unchangedOutputNames) {
314 Set<String> modifiedOutputDefinitionNames = new HashSet<>();
315 Map<String, OperationOutputDefinition> newOutputMap = currentOperationOutputs.stream()
316 .collect(Collectors.toMap(OperationOutputDefinition::getName,
317 (OperationOutputDefinition operationOutputDefinition) -> operationOutputDefinition));
319 Map<String, OperationOutputDefinition> existingOutputMap = existingOperationOutputs.stream()
320 .collect(Collectors.toMap(OperationOutputDefinition::getName,
321 (OperationOutputDefinition operationOutputDefinition) -> operationOutputDefinition));
323 for (String outputName : unchangedOutputNames) {
324 OperationOutputDefinition existingOutputDefinition = existingOutputMap.get(outputName);
325 OperationOutputDefinition newOutputDefinition = newOutputMap.get(outputName);
326 if (!existingOutputDefinition.getType().equals(newOutputDefinition.getType())
327 || !existingOutputDefinition.isRequired().equals(newOutputDefinition.isRequired())) {
328 modifiedOutputDefinitionNames.add(outputName);
331 return modifiedOutputDefinitionNames;
334 private Either<Boolean, ResponseFormat> getMappedOutputErrorResponse(ResponseFormatManager responseFormatManager,
335 Set<String> modifiedMappedOutputs,
337 ActionStatus errorStatus) {
338 String modifiedOutputNameList = String.join(",", modifiedMappedOutputs);
339 LOGGER.error(message, modifiedOutputNameList);
340 ResponseFormat errorResponse = responseFormatManager.getResponseFormat(errorStatus, modifiedOutputNameList);
341 return Either.right(errorResponse);
345 protected ResponseFormatManager getResponseFormatManager() {
346 return ResponseFormatManager.getInstance();
349 private Either<Boolean, ResponseFormat> isInterfaceOperationTypeValid(Operation interfaceOperation,
350 ResponseFormatManager responseFormatManager,
351 InterfaceDefinition interfaceDefinition,
354 Either<Boolean, ResponseFormat> operationTypeEmptyEither =
355 isOperationTypeEmpty(responseFormatManager, interfaceOperation.getName());
356 if (operationTypeEmptyEither.isRight()) {
357 return Either.right(operationTypeEmptyEither.right().value());
360 Either<Boolean, ResponseFormat> operationTypeRegexValidationResponse =
361 isOperationTypeRegexValid(responseFormatManager, interfaceOperation.getName());
362 if (operationTypeRegexValidationResponse.isRight()) {
363 return Either.right(operationTypeRegexValidationResponse.right().value());
366 Either<Boolean, ResponseFormat> operationTypeUniqueResponse = validateOperationTypeUnique(interfaceOperation,
367 interfaceDefinition, isUpdate);
368 if (operationTypeUniqueResponse.isRight()) {
369 return Either.right(operationTypeUniqueResponse.right().value());
371 if (!operationTypeUniqueResponse.left().value()) {
372 LOGGER.error("Interface Operation type {} already in use ", interfaceOperation.getName());
373 ResponseFormat errorResponse = responseFormatManager.getResponseFormat(
374 ActionStatus.INTERFACE_OPERATION_NAME_ALREADY_IN_USE, interfaceOperation.getName());
375 return Either.right(errorResponse);
377 return Either.left(Boolean.TRUE);
380 private Either<Boolean, ResponseFormat> validateInputParameters(Operation interfaceOperation,
381 ResponseFormatManager responseFormatManager) {
382 if (isInputParameterNameEmpty(interfaceOperation)) {
383 LOGGER.error("Interface operation input parameter name can't be empty");
384 ResponseFormat inputResponse =
385 responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_INPUT_NAME_MANDATORY);
386 return Either.right(inputResponse);
389 Either<Boolean, Set<String>> validateInputParametersUniqueResponse =
390 isInputParametersUnique(interfaceOperation);
391 if (validateInputParametersUniqueResponse.isRight()) {
392 LOGGER.error("Interface operation input parameter names {} already in use",
393 validateInputParametersUniqueResponse.right().value());
394 ResponseFormat inputResponse =
395 responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_INPUT_NAME_ALREADY_IN_USE,
396 validateInputParametersUniqueResponse.right().value().toString());
397 return Either.right(inputResponse);
399 return Either.left(Boolean.TRUE);
402 private Either<Boolean, ResponseFormat> validateOutputParameters(Operation interfaceOperation,
403 ResponseFormatManager responseFormatManager) {
404 if (isOutputParameterNameEmpty(interfaceOperation)) {
405 LOGGER.error("Interface operation output parameter name can't be empty");
406 ResponseFormat inputResponse =
407 responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_OUTPUT_NAME_MANDATORY);
408 return Either.right(inputResponse);
411 Either<Boolean, Set<String>> validateOutputParametersUniqueResponse =
412 isOutputParametersUnique(interfaceOperation);
413 if (validateOutputParametersUniqueResponse.isRight()) {
414 LOGGER.error("Interface operation output parameter names {} already in use",
415 validateOutputParametersUniqueResponse.right().value());
416 ResponseFormat inputResponse =
417 responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_OUTPUT_NAME_ALREADY_IN_USE,
418 validateOutputParametersUniqueResponse.right().value().toString());
419 return Either.right(inputResponse);
421 return Either.left(Boolean.TRUE);
424 private Either<Boolean, ResponseFormat> isOperationTypeEmpty(ResponseFormatManager responseFormatManager,
425 String operationType) {
426 if (StringUtils.isEmpty(operationType)) {
427 LOGGER.error("Interface Operation type is mandatory");
428 ResponseFormat errorResponse =
429 responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_NAME_MANDATORY);
430 return Either.right(errorResponse);
432 return Either.left(Boolean.TRUE);
435 private Either<Boolean, ResponseFormat> isOperationTypeRegexValid(ResponseFormatManager responseFormatManager,
436 String operationType) {
437 if (!isValidOperationType(operationType)) {
438 LOGGER.error("Interface Operation type {} is invalid, Operation type should not contain"
439 + "Special character, space, numbers and should not be greater than 200 characters",
441 ResponseFormat errorResponse = responseFormatManager
442 .getResponseFormat(ActionStatus.INTERFACE_OPERATION_NAME_INVALID,
444 return Either.right(errorResponse);
446 return Either.left(Boolean.TRUE);
449 private Either<Boolean, ResponseFormat> validateOperationTypeUnique(Operation interfaceOperation,
450 InterfaceDefinition interfaceDefinition, boolean isUpdate) {
451 boolean isOperationTypeUnique = false;
453 if (interfaceDefinition == null || CollectionUtils.isEmpty(interfaceDefinition.getOperationsMap().values())) {
454 return Either.left(true);
457 Map<String, String> operationTypes = new HashMap<>();
458 interfaceDefinition.getOperationsMap().values()
459 .forEach(operationType -> operationTypes.put(operationType.getUniqueId(), operationType.getName()));
461 if (!operationTypes.values().contains(interfaceOperation.getName())) {
462 isOperationTypeUnique = true;
464 if (!isOperationTypeUnique && isUpdate) {
465 Optional<String> id = operationTypes.entrySet().stream().filter(entry -> Objects.equals(entry.getValue(),
466 interfaceOperation.getName())).map(Map.Entry::getKey).findAny();
467 if (id.isPresent() && id.get().equalsIgnoreCase(interfaceOperation.getUniqueId())) {
468 isOperationTypeUnique = true;
472 return Either.left(isOperationTypeUnique);
475 private Boolean isInputParameterNameEmpty(Operation operationDataDefinition) {
476 return operationDataDefinition.getInputs().getListToscaDataDefinition().stream().anyMatch(
477 inputParam -> inputParam.getName() == null || inputParam.getName().trim().equals(StringUtils.EMPTY));
481 private Either<Boolean, Set<String>> isInputParametersUnique(Operation operationDataDefinition) {
482 Set<String> inputParamNamesSet = new HashSet<>();
483 Set<String> duplicateParamNamesToReturn = new HashSet<>();
484 operationDataDefinition.getInputs().getListToscaDataDefinition()
485 .forEach(inputParam -> {
486 if (!inputParamNamesSet.add(inputParam.getName().trim())) {
487 duplicateParamNamesToReturn.add(inputParam.getName().trim());
490 if (!duplicateParamNamesToReturn.isEmpty()) {
491 return Either.right(duplicateParamNamesToReturn);
493 return Either.left(Boolean.TRUE);
496 private Boolean isOutputParameterNameEmpty(Operation operationDataDefinition) {
497 return operationDataDefinition.getOutputs().getListToscaDataDefinition().stream().anyMatch(
498 outputParam -> outputParam.getName() == null || outputParam.getName().trim().equals(StringUtils.EMPTY));
501 private Either<Boolean, Set<String>> isOutputParametersUnique(Operation operationDataDefinition) {
502 Set<String> outputParamNamesSet = new HashSet<>();
503 Set<String> duplicateParamNamesToReturn = new HashSet<>();
504 operationDataDefinition.getOutputs().getListToscaDataDefinition()
505 .forEach(outputParam -> {
506 if (!outputParamNamesSet.add(outputParam.getName().trim())) {
507 duplicateParamNamesToReturn.add(outputParam.getName().trim());
510 if (!duplicateParamNamesToReturn.isEmpty()) {
511 return Either.right(duplicateParamNamesToReturn);
513 return Either.left(Boolean.TRUE);
516 private Either<Boolean, ResponseFormat> validateInputPropertyExistInComponent(Operation operation,
517 InterfaceDefinition inputInterfaceDefinition, org.openecomp.sdc.be.model.Component component,
518 ResponseFormatManager responseFormatManager) {
520 boolean isOperationInputToInputPropertyMappingValid = false;
521 boolean isOperationInputToOtherOperationOutputMappingValid = false;
522 String mappingName = "";
523 List<OperationInputDefinition> inputListToscaDataDefinition =
524 operation.getInputs().getListToscaDataDefinition();
525 for (OperationInputDefinition inputDefinition : inputListToscaDataDefinition) {
526 if (isOperationInputMappedToComponentInput(inputDefinition, component.getInputs())) {
527 isOperationInputToInputPropertyMappingValid = true;
529 mappingName = inputDefinition.getInputId().contains(".")
530 ? inputDefinition.getInputId().substring(inputDefinition.getInputId().lastIndexOf('.') + 1)
531 : inputDefinition.getInputId();
535 if (isOperationInputToInputPropertyMappingValid) {
536 return Either.left(Boolean.TRUE);
539 //Mapped property not found in the component properties.. Check in other operation output parameters of
540 // component (other operation => not having the same full name)
541 String actualOperationIdentifier = inputInterfaceDefinition.getType() + "." + operation.getName();
542 ListDataDefinition<OperationOutputDefinition> outputListDataDefinition =
543 getOtherOperationOutputsOfComponent(actualOperationIdentifier, component.getInterfaces());
545 List<OperationOutputDefinition> componentOutputsFromOtherOperations =
546 outputListDataDefinition.getListToscaDataDefinition();
547 if (validateOutputExistsInComponent(mappingName, componentOutputsFromOtherOperations)) {
548 isOperationInputToOtherOperationOutputMappingValid = true;
550 //Get the output parameter display name from the full name
551 mappingName = getOperationOutputName(mappingName);
554 if (!isOperationInputToOtherOperationOutputMappingValid) {
555 LOGGER.error("Interface operation input parameter property {} not found in component input properties or"
556 + " outputs of other operations.", mappingName);
557 ResponseFormat inputResponse = responseFormatManager
558 .getResponseFormat(ActionStatus.INTERFACE_OPERATION_INPUT_PROPERTY_NOT_FOUND_IN_COMPONENT,
559 mappingName, component.getComponentType().getValue());
560 return Either.right(inputResponse);
562 return Either.left(Boolean.TRUE);
565 private boolean validateOutputExistsInComponent(String mappedOutputName,
566 List<OperationOutputDefinition> outputs) {
567 return outputs.stream()
568 .anyMatch(output -> output.getName().equals(mappedOutputName));
572 * Get the input definitions of other operations of the component from current as well as other interfaces.
573 * @param currentOperationIdentifier Identifier for the request operation (interface_name.operation_name)
574 * @param componentInterfaces Interfaces of the component
576 private List<OperationInputDefinition> getOtherOperationInputsOfComponent(String currentOperationIdentifier,
577 Map<String, InterfaceDefinition>
578 componentInterfaces) {
579 List<OperationInputDefinition> otherOperationInputs = new ArrayList<>();
580 if (MapUtils.isEmpty(componentInterfaces)) {
581 return otherOperationInputs;
583 for (Map.Entry<String, InterfaceDefinition> interfaceDefinitionEntry : componentInterfaces.entrySet()) {
584 final Map<String, OperationDataDefinition> operations = interfaceDefinitionEntry.getValue().getOperations();
585 if (MapUtils.isEmpty(operations)) {
588 for (Map.Entry<String, OperationDataDefinition> operationEntry : operations.entrySet()) {
589 ListDataDefinition<OperationInputDefinition> inputs = operationEntry.getValue().getInputs();
590 String expectedOperationIdentifier =
591 interfaceDefinitionEntry.getValue().getType() + "." + operationEntry.getValue().getName();
592 if (!currentOperationIdentifier.equals(expectedOperationIdentifier) && !inputs.isEmpty()) {
593 otherOperationInputs.addAll(inputs.getListToscaDataDefinition());
597 return otherOperationInputs;
601 * Get the output of an operation in an interface.
602 * @param inputOperationId Unique identifier for the request operation
603 * @param componentInterfaces Interfaces of the component
605 private List<OperationOutputDefinition> getInterfaceOperationOutputs(String inputOperationId,
606 Map<String, InterfaceDefinition>
607 componentInterfaces) {
608 List<OperationOutputDefinition> operationOutputDefinitions = new ArrayList<>();
609 if (MapUtils.isEmpty(componentInterfaces)) {
610 return operationOutputDefinitions;
612 for (Map.Entry<String, InterfaceDefinition> interfaceDefinitionEntry : componentInterfaces.entrySet()) {
613 final Map<String, OperationDataDefinition> operations = interfaceDefinitionEntry.getValue().getOperations();
614 if (MapUtils.isEmpty(operations)) {
617 for (Map.Entry<String, OperationDataDefinition> operationEntry : operations.entrySet()) {
618 String expectedOperationId = operationEntry.getValue().getUniqueId();
619 if (expectedOperationId.equals(inputOperationId)) {
620 ListDataDefinition<OperationOutputDefinition> operationOutputs =
621 operationEntry.getValue().getOutputs();
622 return (Objects.isNull(operationOutputs) || operationOutputs.isEmpty())
623 ? operationOutputDefinitions
624 : operationOutputs.getListToscaDataDefinition();
628 return operationOutputDefinitions;
631 private boolean isValidOperationType(String operationType) {
632 return Pattern.matches(TYPE_VALIDATION_REGEX, operationType);