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 java.util.Collection;
21 import java.util.HashMap;
22 import java.util.HashSet;
24 import java.util.Objects;
25 import java.util.Optional;
27 import java.util.regex.Pattern;
28 import java.util.stream.Collectors;
29 import org.apache.commons.collections.CollectionUtils;
30 import org.apache.commons.collections.MapUtils;
31 import org.apache.commons.lang.StringUtils;
32 import org.elasticsearch.common.Strings;
33 import org.openecomp.sdc.be.components.impl.ResponseFormatManager;
34 import org.openecomp.sdc.be.dao.api.ActionStatus;
35 import org.openecomp.sdc.be.model.InterfaceDefinition;
36 import org.openecomp.sdc.be.model.Operation;
37 import org.openecomp.sdc.be.model.Resource;
38 import org.openecomp.sdc.exception.ResponseFormat;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41 import org.springframework.stereotype.Component;
43 @Component("interfaceOperationValidation")
44 public class InterfaceOperationValidation {
46 private static final String TYPE_VALIDATION_REGEX = "^[a-zA-Z]{1,200}$";
47 private static final int DESCRIPTION_MAX_LENGTH = 200;
49 private static final Logger LOGGER = LoggerFactory.getLogger(InterfaceOperationValidation.class);
51 public Either<Boolean, ResponseFormat> validateInterfaceOperations(
52 Collection<Operation> interfaceOperations, org.openecomp.sdc.be.model.Component component, boolean isUpdate) {
54 for(Operation interfaceOperation : interfaceOperations) {
55 Either<Boolean, ResponseFormat> interfaceOperationValidatorResponse = validateInterfaceOperation(
56 interfaceOperation, component, isUpdate);
57 if (interfaceOperationValidatorResponse.isRight()) {
58 return interfaceOperationValidatorResponse;
61 return Either.left(Boolean.TRUE);
64 private Either<Boolean, ResponseFormat> validateInterfaceOperation(Operation interfaceOperation,
65 org.openecomp.sdc.be.model.Component component, boolean isUpdate) {
66 ResponseFormatManager responseFormatManager = getResponseFormatManager();
68 Either<Boolean, ResponseFormat> interfaceOperationTypeResponse = isInterfaceOperationTypeValid(interfaceOperation,
69 responseFormatManager, component, isUpdate);
70 if (interfaceOperationTypeResponse.isRight()) {
71 return Either.right(interfaceOperationTypeResponse.right().value());
74 Either<Boolean, ResponseFormat> descriptionResponseEither = isValidDescription(responseFormatManager,
75 interfaceOperation.getDescription());
76 if (descriptionResponseEither.isRight()) {
77 return Either.right(descriptionResponseEither.right().value());
80 Either<Boolean, ResponseFormat> inputParametersResponse = validateInputParameters(interfaceOperation,
81 responseFormatManager);
82 if(inputParametersResponse.isRight()) {
83 return Either.right(inputParametersResponse.right().value());
86 Either<Boolean, ResponseFormat> outputParametersResponse = validateOutputParameters(interfaceOperation,
87 responseFormatManager);
88 if(outputParametersResponse.isRight()) {
89 return Either.right(outputParametersResponse.right().value());
92 return Either.left(Boolean.TRUE);
95 private Either<Boolean, ResponseFormat> isInterfaceOperationTypeValid(Operation interfaceOperation,
96 ResponseFormatManager responseFormatManager,
97 org.openecomp.sdc.be.model.Component component, boolean isUpdate) {
99 Either<Boolean, ResponseFormat> operationTypeEmptyEither =
100 isOperationTypeEmpty(responseFormatManager, interfaceOperation.getName());
101 if (operationTypeEmptyEither.isRight()) {
102 return Either.right(operationTypeEmptyEither.right().value());
105 Either<Boolean, ResponseFormat> operationTypeRegexValidationResponse =
106 isOperationTypeRegexValid(responseFormatManager, interfaceOperation.getName());
107 if (operationTypeRegexValidationResponse.isRight()) {
108 return Either.right(operationTypeRegexValidationResponse.right().value());
111 Either<Boolean, ResponseFormat> operationTypeUniqueResponse = validateOperationTypeUnique(interfaceOperation,
112 component, isUpdate, responseFormatManager );
113 if(operationTypeUniqueResponse.isRight()) {
114 return Either.right(operationTypeUniqueResponse.right().value());
116 if (!operationTypeUniqueResponse.left().value()) {
117 LOGGER.error("Interface Operation type {} already in use ", interfaceOperation.getName());
118 ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus
119 .INTERFACE_OPERATION_TYPE_ALREADY_IN_USE, interfaceOperation.getName());
120 return Either.right(errorResponse);
122 return Either.left(Boolean.TRUE);
125 private Either<Boolean, ResponseFormat> isOperationTypeRegexValid(ResponseFormatManager responseFormatManager,
126 String operationType) {
127 if (!isValidOperationType(operationType)) {
128 LOGGER.error("Interface Operation type {} is invalid, Operation type should not contain" +
129 "Special character, space, numbers and should not be greater than 200 characters", operationType);
130 ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus
131 .INTERFACE_OPERATION_TYPE_INVALID, operationType);
132 return Either.right(errorResponse);
134 return Either.left(Boolean.TRUE);
137 private Either<Boolean, ResponseFormat> isOperationTypeEmpty(ResponseFormatManager responseFormatManager,
138 String operationType) {
139 if (StringUtils.isEmpty(operationType)) {
140 LOGGER.error("Interface Operation type is mandatory");
141 ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus
142 .INTERFACE_OPERATION_TYPE_MANDATORY);
143 return Either.right(errorResponse);
145 return Either.left(Boolean.TRUE);
148 private Either<Boolean, ResponseFormat> isValidDescription(ResponseFormatManager responseFormatManager,
149 String description) {
150 if (!Strings.isNullOrEmpty(description) && description.length() > DESCRIPTION_MAX_LENGTH) {
151 LOGGER.error("Interface Operation description {} is invalid, maximum 200 characters allowed", description);
152 ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus
153 .INTERFACE_OPERATION_DESCRIPTION_MAX_LENGTH);
154 return Either.right(errorResponse);
156 return Either.left(Boolean.TRUE);
159 private boolean isValidOperationType(String operationType) {
160 return Pattern.matches(TYPE_VALIDATION_REGEX, operationType);
163 private Either<Boolean, ResponseFormat> validateOperationTypeUnique(
164 Operation interfaceOperation,
165 org.openecomp.sdc.be.model.Component component,
167 ResponseFormatManager responseFormatManager) {
168 boolean isOperationTypeUnique = false;
170 Map<String, InterfaceDefinition> interfaceDefinitionMap = ((Resource)component).getInterfaces();
171 if(interfaceDefinitionMap.isEmpty()){
172 isOperationTypeUnique = true;
173 return Either.left(isOperationTypeUnique);
176 Collection<Operation> allOperations = interfaceDefinitionMap.values().stream()
177 .filter(a -> MapUtils.isNotEmpty(a.getOperationsMap()))
178 .map(a -> a.getOperationsMap().values()).flatMap(Collection::stream)
179 .collect(Collectors.toList());
180 if(CollectionUtils.isEmpty(allOperations)){
181 isOperationTypeUnique = true;
182 return Either.left(isOperationTypeUnique);
185 Map<String, String> operationTypes = new HashMap<>();
186 allOperations.forEach(operationType -> operationTypes.put(operationType.getUniqueId(), operationType.getName()));
188 if (!operationTypes.values().contains(interfaceOperation.getName())){
189 isOperationTypeUnique = true;
191 if (!isOperationTypeUnique && isUpdate){
192 Optional<String> id = operationTypes.entrySet().stream().filter(entry -> Objects.equals(entry.getValue(), interfaceOperation.getName()))
193 .map(Map.Entry::getKey).findAny();
194 if(id.isPresent() && id.get().equalsIgnoreCase(interfaceOperation.getUniqueId())){
195 isOperationTypeUnique = true;
199 return Either.left(isOperationTypeUnique);
201 private Either<Boolean, ResponseFormat> validateInputParameters(Operation interfaceOperation,
202 ResponseFormatManager responseFormatManager) {
203 if (isInputParameterNameEmpty(interfaceOperation)) {
204 LOGGER.error("Interface operation input parameter name can't be empty");
205 ResponseFormat inputResponse = responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_INPUT_NAME_MANDATORY);
206 return Either.right(inputResponse);
209 Either<Boolean, Set<String>> validateInputParametersUniqueResponse = isInputParametersUnique(interfaceOperation);
210 if(validateInputParametersUniqueResponse.isRight()) {
211 LOGGER.error("Interface operation input parameter names {} already in use",
212 validateInputParametersUniqueResponse.right().value());
213 ResponseFormat inputResponse = responseFormatManager.getResponseFormat(ActionStatus
214 .INTERFACE_OPERATION_INPUT_NAME_ALREADY_IN_USE, validateInputParametersUniqueResponse.right().value().toString());
215 return Either.right(inputResponse);
217 return Either.left(Boolean.TRUE);
221 private Either<Boolean, ResponseFormat> validateOutputParameters(Operation interfaceOperation,
222 ResponseFormatManager responseFormatManager) {
223 if (isOutputParameterNameEmpty(interfaceOperation)) {
224 LOGGER.error("Interface operation output parameter name can't be empty");
225 ResponseFormat inputResponse = responseFormatManager.getResponseFormat(ActionStatus.INTERFACE_OPERATION_OUTPUT_NAME_MANDATORY);
226 return Either.right(inputResponse);
229 Either<Boolean, Set<String>> validateOutputParametersUniqueResponse = isOutputParametersUnique(interfaceOperation);
230 if(validateOutputParametersUniqueResponse.isRight()) {
231 LOGGER.error("Interface operation output parameter names {} already in use",
232 validateOutputParametersUniqueResponse.right().value());
233 ResponseFormat inputResponse = responseFormatManager.getResponseFormat(ActionStatus
234 .INTERFACE_OPERATION_OUTPUT_NAME_ALREADY_IN_USE, validateOutputParametersUniqueResponse.right().value().toString());
235 return Either.right(inputResponse);
237 return Either.left(Boolean.TRUE);
241 private Either<Boolean, Set<String>> isInputParametersUnique(Operation operationDataDefinition) {
242 Set<String> inputParamNamesSet = new HashSet<>();
243 Set<String> duplicateParamNamesToReturn = new HashSet<>();
244 operationDataDefinition.getInputs().getListToscaDataDefinition()
245 .forEach(inputParam -> {
246 if(!inputParamNamesSet.add(inputParam.getName().trim())) {
247 duplicateParamNamesToReturn.add(inputParam.getName().trim());
250 if(!duplicateParamNamesToReturn.isEmpty()) {
251 return Either.right(duplicateParamNamesToReturn);
253 return Either.left(Boolean.TRUE);
256 private Either<Boolean, Set<String>> isOutputParametersUnique(Operation operationDataDefinition) {
257 Set<String> outputParamNamesSet = new HashSet<>();
258 Set<String> duplicateParamNamesToReturn = new HashSet<>();
259 operationDataDefinition.getOutputs().getListToscaDataDefinition()
260 .forEach(outputParam -> {
261 if(!outputParamNamesSet.add(outputParam.getName().trim())) {
262 duplicateParamNamesToReturn.add(outputParam.getName().trim());
265 if(!duplicateParamNamesToReturn.isEmpty()) {
266 return Either.right(duplicateParamNamesToReturn);
268 return Either.left(Boolean.TRUE);
271 private Boolean isInputParameterNameEmpty(Operation operationDataDefinition) {
272 return operationDataDefinition.getInputs().getListToscaDataDefinition().stream()
273 .anyMatch(inputParam -> inputParam.getName() == null || inputParam.getName().trim().equals(StringUtils.EMPTY));
275 private Boolean isOutputParameterNameEmpty(Operation operationDataDefinition) {
276 return operationDataDefinition.getInputs().getListToscaDataDefinition().stream()
277 .anyMatch(inputParam -> inputParam.getName() == null || inputParam.getName().trim().equals(StringUtils.EMPTY));
280 private boolean validateOperationTypeUniqueForUpdate(Operation interfaceOperation, Map<String, String> operationTypes) {
281 boolean isOperationTypeUnique = false;
282 Optional<String> id = operationTypes.entrySet().stream().filter(entry -> Objects.equals(entry.getValue(), interfaceOperation.getName()))
283 .map(Map.Entry::getKey).findAny();
284 if(id.isPresent() && id.get().equalsIgnoreCase(interfaceOperation.getUniqueId())){
285 isOperationTypeUnique = true;
287 return isOperationTypeUnique;
290 protected ResponseFormatManager getResponseFormatManager() {
291 return ResponseFormatManager.getInstance();