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 fj.data.Either;
20 import org.apache.commons.collections.CollectionUtils;
21 import org.apache.commons.collections.MapUtils;
22 import org.apache.commons.lang.StringUtils;
23 import org.openecomp.sdc.be.components.impl.ResponseFormatManager;
24 import org.openecomp.sdc.be.dao.api.ActionStatus;
25 import org.openecomp.sdc.be.model.ComponentParametersView;
26 import org.openecomp.sdc.be.model.InterfaceDefinition;
27 import org.openecomp.sdc.be.model.Operation;
28 import org.openecomp.sdc.be.model.Resource;
29 import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade;
30 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
31 import org.openecomp.sdc.exception.ResponseFormat;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34 import org.springframework.beans.factory.annotation.Autowired;
35 import org.springframework.stereotype.Component;
37 import java.util.Collection;
38 import java.util.HashMap;
39 import java.util.HashSet;
42 import java.util.regex.Pattern;
43 import java.util.stream.Collectors;
45 @Component("interfaceOperationValidation")
46 public class InterfaceOperationValidation {
49 private ToscaOperationFacade toscaOperationFacade;
50 private static final String TYPE_VALIDATION_REGEX = "^[a-zA-Z]{1,200}$";
51 private static final int DESCRIPTION_MAX_LENGTH = 200;
53 private static final Logger LOGGER = LoggerFactory.getLogger(InterfaceOperationValidation.class);
55 public Either<Boolean, ResponseFormat> validateInterfaceOperations(
56 Collection<Operation> interfaceOperations,
57 String resourceId, boolean isUpdate) {
59 for(Operation interfaceOperation : interfaceOperations) {
60 Either<Boolean, ResponseFormat> interfaceOperationValidatorResponse = validateInterfaceOperation(
61 interfaceOperation, resourceId, isUpdate);
62 if (interfaceOperationValidatorResponse.isRight()) {
63 return interfaceOperationValidatorResponse;
66 return Either.left(Boolean.TRUE);
69 private Either<Boolean, ResponseFormat> validateInterfaceOperation(Operation interfaceOperation,
70 String resourceId, boolean isUpdate) {
71 ResponseFormatManager responseFormatManager = getResponseFormatManager();
73 Either<Boolean, ResponseFormat> interfaceOperationTypeResponse = validateInterfaceOperationType(interfaceOperation,
74 responseFormatManager, resourceId, isUpdate);
75 if (interfaceOperationTypeResponse != null) {
76 return interfaceOperationTypeResponse;
79 Either<Boolean, ResponseFormat> descriptionResponseEither = validateDescription(responseFormatManager,
80 interfaceOperation.getDescription());
81 if (descriptionResponseEither != null) {
82 return descriptionResponseEither;
85 Either<Boolean, ResponseFormat> inputParametersResponse = validateInputParameters(interfaceOperation,
86 responseFormatManager);
87 if(inputParametersResponse != null) {
88 return inputParametersResponse;
90 return Either.left(true);
93 private Either<Boolean, ResponseFormat> validateInterfaceOperationType(Operation interfaceOperation,
94 ResponseFormatManager responseFormatManager,
95 String resourceId, boolean isUpdate) {
97 Either<Boolean, ResponseFormat> operationTypeEmptyEither = isOperationTypeEmpty(responseFormatManager,
98 interfaceOperation.getName()); // treating name as type for now
99 if (operationTypeEmptyEither != null) {
100 return operationTypeEmptyEither;
103 Either<Boolean, ResponseFormat> operationTypeRegexValidationResponse =
104 validateOperationTypeRegex(responseFormatManager, interfaceOperation.getName());
105 if (operationTypeRegexValidationResponse != null) {
106 return operationTypeRegexValidationResponse;
109 Either<Boolean, ResponseFormat> operationTypeUniqueResponse = validateOperationTypeUnique(interfaceOperation,
110 resourceId, isUpdate, responseFormatManager );
111 if(operationTypeUniqueResponse.isRight()) {
112 return Either.right(operationTypeUniqueResponse.right().value());
114 if (!operationTypeUniqueResponse.left().value()) {
115 LOGGER.debug("Interface Operation type {} already in use ", interfaceOperation.getName());
116 ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus
117 .INTERFACE_OPERATION_TYPE_ALREADY_IN_USE, interfaceOperation.getName());
118 return Either.right(errorResponse);
123 private Either<Boolean, ResponseFormat> validateOperationTypeRegex(ResponseFormatManager responseFormatManager,
124 String operationType) {
125 if (!isValidOperationType(operationType)) {
126 LOGGER.debug("Interface Operation type {} is invalid, Operation type should not contain" +
127 "Special character, space and should not be greater than 200 characters", operationType);
128 ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus
129 .INTERFACE_OPERATION_TYPE_INVALID, operationType);
130 return Either.right(errorResponse);
135 private Either<Boolean, ResponseFormat> isOperationTypeEmpty(ResponseFormatManager responseFormatManager,
136 String operationType) {
137 if (StringUtils.isEmpty(operationType)) {
138 LOGGER.debug("Interface Operation type is mandatory, it can't be empty");
139 ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus
140 .INTERFACE_OPERATION_TYPE_MANDATORY);
141 return Either.right(errorResponse);
146 private Either<Boolean, ResponseFormat> validateDescription(ResponseFormatManager responseFormatManager,
147 String description) {
148 if (description.length() > DESCRIPTION_MAX_LENGTH) {
149 LOGGER.debug("Interface Operation description {} is invalid, maximum 200 characters allowed", description);
150 ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus
151 .INTERFACE_OPERATION_DESCRIPTION_MAX_LENGTH);
152 return Either.right(errorResponse);
157 private boolean isValidOperationType(String operationType) {
158 return Pattern.matches(TYPE_VALIDATION_REGEX, operationType);
161 private Either<Boolean, ResponseFormat> validateOperationTypeUnique(Operation interfaceOperation,
164 ResponseFormatManager responseFormatManager) {
165 boolean isOperationTypeUnique = false;
166 ComponentParametersView filter = new ComponentParametersView(true);
167 filter.setIgnoreInterfaces(false);
168 Either<Resource, StorageOperationStatus> interfaceOperationOrigin = toscaOperationFacade
169 .getToscaElement(resourceId, filter);
170 if (interfaceOperationOrigin.isRight()){
171 LOGGER.debug("Failed to fetch interface operation information by resource id {} ", resourceId);
172 return Either.right(responseFormatManager.getResponseFormat(ActionStatus.GENERAL_ERROR));
175 Collection<InterfaceDefinition> interfaceDefinitions = interfaceOperationOrigin.left().value()
176 .getInterfaces().values();
177 if(CollectionUtils.isEmpty(interfaceDefinitions)){
178 isOperationTypeUnique = true;
179 return Either.left(isOperationTypeUnique);
181 Collection<Operation> allOperations = interfaceDefinitions.stream()
182 .filter(a -> MapUtils.isNotEmpty(a.getOperationsMap()))
183 .map(a -> a.getOperationsMap().values()).flatMap(Collection::stream)
184 .collect(Collectors.toList());
185 if(CollectionUtils.isEmpty(allOperations)){
186 isOperationTypeUnique = true;
187 return Either.left(isOperationTypeUnique);
190 Map<String, String> operationTypes = new HashMap<>();
191 allOperations.forEach(operationType -> operationTypes.put(operationType.getUniqueId(),
192 operationType.getName()) );
195 isOperationTypeUnique = validateOperationTypeUniqueForUpdate(interfaceOperation, operationTypes);
198 if (!operationTypes.values().contains(interfaceOperation.getName())){
199 isOperationTypeUnique = true;
201 return Either.left(isOperationTypeUnique);
203 private Either<Boolean, ResponseFormat> validateInputParameters(Operation interfaceOperation,
204 ResponseFormatManager responseFormatManager) {
205 Either<Boolean, Set<String>> validateInputParametersUniqueResponse = validateInputParametersUnique(interfaceOperation);
206 if(validateInputParametersUniqueResponse.isRight()) {
207 LOGGER.debug("Interface operation input parameter names {} are invalid, Input parameter names should be unique",
208 validateInputParametersUniqueResponse.right().value().toString());
209 ResponseFormat inputResponse = responseFormatManager.getResponseFormat(ActionStatus
210 .INTERFACE_OPERATION_INPUT_NAME_INVALID, validateInputParametersUniqueResponse.right().value().toString());
211 return Either.right(inputResponse);
216 private Either<Boolean, Set<String>> validateInputParametersUnique(Operation operationDataDefinition) {
218 Set<String> inputParamNamesSet = new HashSet<>();
219 Set<String> duplicateParamNamesToReturn = new HashSet<>();
220 operationDataDefinition.getInputs().getListToscaDataDefinition()
221 .forEach(inputParam -> {
222 if(!inputParamNamesSet.add(inputParam.getLabel())) {
223 duplicateParamNamesToReturn.add(inputParam.getLabel());
226 if(!duplicateParamNamesToReturn.isEmpty()) {
227 return Either.right(duplicateParamNamesToReturn);
229 return Either.left(Boolean.TRUE);
233 private boolean validateOperationTypeUniqueForUpdate(Operation interfaceOperation,
234 Map<String, String> operationTypes) {
235 boolean isOperationTypeUnique = false;
236 for(Map.Entry<String, String> entry : operationTypes.entrySet()){
237 if (entry.getKey().equals(interfaceOperation.getUniqueId()) && entry.getValue().
238 equals(interfaceOperation.getName())) {
239 isOperationTypeUnique = true;
242 if(entry.getKey().equals(interfaceOperation.getUniqueId()) && !operationTypes.values()
243 .contains(interfaceOperation.getName())){
244 isOperationTypeUnique = true;
247 return isOperationTypeUnique;
250 protected ResponseFormatManager getResponseFormatManager() {
251 return ResponseFormatManager.getInstance();