2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.sdc.be.components.validation;
23 import com.google.common.collect.ImmutableSet;
24 import fj.data.Either;
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.List;
28 import java.util.Objects;
29 import java.util.Optional;
31 import org.apache.commons.lang3.StringUtils;
32 import org.openecomp.sdc.be.components.impl.ResponseFormatManager;
33 import org.openecomp.sdc.be.components.impl.utils.NodeFilterConstraintAction;
34 import org.openecomp.sdc.be.dao.api.ActionStatus;
35 import org.openecomp.sdc.be.datamodel.utils.ConstraintConvertor;
36 import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
37 import org.openecomp.sdc.be.impl.ComponentsUtils;
38 import org.openecomp.sdc.be.model.Component;
39 import org.openecomp.sdc.be.model.ComponentInstance;
40 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
41 import org.openecomp.sdc.be.model.PropertyDefinition;
42 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
43 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
44 import org.openecomp.sdc.be.ui.model.UIConstraint;
45 import org.openecomp.sdc.exception.ResponseFormat;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48 import org.springframework.beans.factory.annotation.Autowired;
49 import org.springframework.util.CollectionUtils;
51 @org.springframework.stereotype.Component("NodeFilterValidator")
52 public class NodeFilterValidator {
54 private static final String SOURCE = "Source";
55 public static final Set<String> comparableTypes = ImmutableSet.of(ToscaPropertyType.STRING.getType(),
56 ToscaPropertyType.INTEGER.getType(), ToscaPropertyType.FLOAT.getType());
57 public static final Set<String> schemableTypes =
58 ImmutableSet.of(ToscaPropertyType.MAP.getType(), ToscaPropertyType.LIST.getType());
59 public static final Set<String> comparableConstraintsOperators =
60 ImmutableSet.of(ConstraintConvertor.GREATER_THAN_OPERATOR, ConstraintConvertor.LESS_THAN_OPERATOR);
62 protected final ToscaOperationFacade toscaOperationFacade;
63 protected final ComponentsUtils componentsUtils;
65 private static final Logger LOGGER = LoggerFactory.getLogger(NodeFilterValidator.class);
68 public NodeFilterValidator(final ToscaOperationFacade toscaOperationFacade,
69 final ComponentsUtils componentsUtils) {
70 this.toscaOperationFacade = toscaOperationFacade;
71 this.componentsUtils = componentsUtils;
74 public Either<Boolean, ResponseFormat> validateComponentInstanceExist(final Component component,
75 final String componentInstanceId) {
76 if (component == null || StringUtils.isEmpty(componentInstanceId)) {
77 LOGGER.error("Input data cannot be empty");
78 return getErrorResponse(ActionStatus.FILTER_NOT_FOUND);
80 if (CollectionUtils.isEmpty(component.getComponentInstances()) ||
81 component.getComponentInstances().stream()
82 .noneMatch(ci -> ci.getUniqueId().equals(componentInstanceId))) {
83 LOGGER.error("Component Instance list is empty");
84 return getErrorResponse(ActionStatus.FILTER_NOT_FOUND);
86 return Either.left(Boolean.TRUE);
89 private Either<Boolean, ResponseFormat> getErrorResponse(ActionStatus actionStatus, String... variables) {
90 ResponseFormat errorResponse = ResponseFormatManager.getInstance().getResponseFormat(actionStatus, variables);
91 return Either.right(errorResponse);
94 public Either<Boolean, ResponseFormat> validateFilter(final Component parentComponent,
95 final String componentInstanceId,
96 final List<String> uiConstraints,
97 final NodeFilterConstraintAction action) {
99 if (NodeFilterConstraintAction.ADD == action || NodeFilterConstraintAction.UPDATE == action) {
100 for (final String uiConstraint : uiConstraints) {
101 final UIConstraint constraint = new ConstraintConvertor().convert(uiConstraint);
102 if (ConstraintConvertor.PROPERTY_CONSTRAINT.equals(constraint.getSourceType())) {
103 final Either<Boolean, ResponseFormat> booleanResponseFormatEither =
104 validatePropertyConstraint(parentComponent, componentInstanceId, constraint);
105 if (booleanResponseFormatEither.isRight()) {
106 return booleanResponseFormatEither;
108 } else if (ConstraintConvertor.STATIC_CONSTRAINT.equals(constraint.getSourceType())) {
109 final Either<Boolean, ResponseFormat> booleanResponseFormatEither =
110 validateStaticValueAndOperator(parentComponent, componentInstanceId, constraint);
111 if (booleanResponseFormatEither.isRight()) {
112 return booleanResponseFormatEither;
117 } catch (final Exception e) {
118 LOGGER.debug("Provided constraint" + uiConstraints, e);
119 return Either.right(componentsUtils.getResponseFormat(ActionStatus.CONSTRAINT_FORMAT_INCORRECT));
122 return Either.left(true);
125 private Either<Boolean, ResponseFormat> validatePropertyConstraint(final Component parentComponent,
126 final String componentInstanceId,
127 final UIConstraint uiConstraint) {
128 String source = SOURCE;
129 final Optional<ComponentInstance> optionalComponentInstance;
131 final List<PropertyDefinition> propertyDefinitions = parentComponent.getProperties();
132 List<? extends PropertyDefinition> sourcePropertyDefinition =
133 parentComponent.getName().equals(uiConstraint.getSourceName()) &&
134 propertyDefinitions != null ? propertyDefinitions : Collections.emptyList();
136 if (sourcePropertyDefinition.isEmpty() && !parentComponent.getName().equals(uiConstraint.getSourceName())) {
137 optionalComponentInstance = parentComponent.getComponentInstances().stream()
138 .filter(componentInstance -> uiConstraint.getSourceName()
139 .equals(componentInstance
143 if (optionalComponentInstance.isPresent()) {
144 final List<ComponentInstanceProperty> componentInstanceProperties =
145 parentComponent.getComponentInstancesProperties()
146 .get(optionalComponentInstance.get().getUniqueId());
147 sourcePropertyDefinition =
148 componentInstanceProperties == null ? new ArrayList<>() : componentInstanceProperties;
152 if (!CollectionUtils.isEmpty(sourcePropertyDefinition)) {
153 final Optional<? extends PropertyDefinition> sourceSelectedProperty = sourcePropertyDefinition.stream()
154 .filter(property -> uiConstraint
156 .equals(property.getName()))
159 final Optional<? extends PropertyDefinition> targetComponentInstanceProperty =
160 parentComponent.getComponentInstancesProperties().get(componentInstanceId).stream()
161 .filter(property -> uiConstraint.getServicePropertyName().equals(property.getName()))
164 source = !targetComponentInstanceProperty.isPresent() ? "Target" : SOURCE;
165 if (sourceSelectedProperty.isPresent() && targetComponentInstanceProperty.isPresent()) {
166 return validatePropertyData(uiConstraint, sourceSelectedProperty, targetComponentInstanceProperty);
170 final String missingProperty =
171 source.equals(SOURCE) ? uiConstraint.getValue().toString() : uiConstraint.getServicePropertyName();
174 componentsUtils.getResponseFormat(ActionStatus.MAPPED_PROPERTY_NOT_FOUND, source, missingProperty));
177 private Either<Boolean, ResponseFormat> validatePropertyData(UIConstraint uiConstraint,
178 Optional<? extends PropertyDefinition> sourceSelectedProperty,
179 Optional<? extends PropertyDefinition> targetComponentInstanceProperty) {
180 if (sourceSelectedProperty.isPresent() && targetComponentInstanceProperty.isPresent()) {
181 final PropertyDefinition sourcePropDefinition = sourceSelectedProperty.get();
182 final String sourceType = sourcePropDefinition.getType();
183 final PropertyDefinition targetPropDefinition = targetComponentInstanceProperty.get();
184 final String targetType = targetPropDefinition.getType();
185 if (sourceType.equals(targetType)) {
186 if (schemableTypes.contains(sourceType)) {
187 final SchemaDefinition sourceSchemaDefinition = sourcePropDefinition.getSchema();
188 final SchemaDefinition targetSchemaDefinition = targetPropDefinition.getSchema();
189 if (!sourceSchemaDefinition.equals(targetSchemaDefinition)) {
191 .right(componentsUtils.getResponseFormat(ActionStatus.SOURCE_TARGET_SCHEMA_MISMATCH,
192 uiConstraint.getServicePropertyName(), uiConstraint.getValue().toString()));
195 return Either.left(Boolean.TRUE);
197 return Either.right(componentsUtils.getResponseFormat(ActionStatus.SOURCE_TARGET_PROPERTY_TYPE_MISMATCH,
198 uiConstraint.getServicePropertyName(), uiConstraint.getValue().toString()));
202 "Null value passed to `validatePropertyData` - sourceSelectedProperty: '{}' - targetComponentInstanceProperty: '{}'",
203 sourceSelectedProperty, targetComponentInstanceProperty);
204 return Either.right(componentsUtils
205 .getResponseFormat(ActionStatus.GENERAL_ERROR, uiConstraint.getServicePropertyName(),
206 uiConstraint.getValue().toString()));
210 private Either<Boolean, ResponseFormat> validateStaticValueAndOperator(
211 final Component parentComponent,
212 final String componentInstanceId, final UIConstraint uiConstraint) {
213 if (!(Objects.nonNull(uiConstraint) && uiConstraint.getValue() instanceof String)) {
214 return Either.left(false);
216 final Optional<ComponentInstanceProperty> componentInstanceProperty =
217 parentComponent.getComponentInstancesProperties().get(componentInstanceId).stream()
218 .filter(property -> uiConstraint.getServicePropertyName().equals(property.getName()))
221 if (!componentInstanceProperty.isPresent()) {
222 return Either.right(componentsUtils.getResponseFormat(ActionStatus.SELECTED_PROPERTY_NOT_PRESENT,
223 uiConstraint.getServicePropertyName()));
225 if (comparableConstraintsOperators.contains(uiConstraint.getConstraintOperator()) && !comparableTypes.contains(
226 componentInstanceProperty.get().getType())) {
227 return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_OPERATOR_PROVIDED,
228 uiConstraint.getServicePropertyName(), uiConstraint.getConstraintOperator()));
231 return isValidValueCheck(componentInstanceProperty.get().getType(), String.valueOf(uiConstraint.getValue()),
232 uiConstraint.getServicePropertyName());
235 private Either<Boolean, ResponseFormat> isValidValueCheck(String type, String value, String propertyName) {
237 ToscaPropertyType toscaPropertyType = ToscaPropertyType.isValidType(type);
238 if (Objects.isNull(toscaPropertyType)) {
240 componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_PROPERTY_TYPE, type, propertyName));
242 if (toscaPropertyType.getValidator().isValid(value, null)) {
243 return Either.left(Boolean.TRUE);
246 componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_VALUE_PROVIDED, type, propertyName, value));