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=========================================================
20 package org.openecomp.sdc.be.components.validation;
22 import com.google.gson.Gson;
23 import fj.data.Either;
24 import java.util.Collection;
25 import java.util.List;
27 import java.util.Optional;
29 import java.util.stream.Collectors;
30 import org.apache.commons.collections4.CollectionUtils;
31 import org.apache.commons.lang3.StringUtils;
32 import org.openecomp.sdc.be.dao.api.ActionStatus;
33 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
34 import org.openecomp.sdc.be.datatypes.elements.ToscaGetFunctionDataDefinition;
35 import org.openecomp.sdc.be.datatypes.enums.PropertyFilterTargetType;
36 import org.openecomp.sdc.be.datatypes.enums.PropertySource;
37 import org.openecomp.sdc.be.impl.ComponentsUtils;
38 import org.openecomp.sdc.be.model.CapabilityDefinition;
39 import org.openecomp.sdc.be.model.Component;
40 import org.openecomp.sdc.be.model.ComponentInstance;
41 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
42 import org.openecomp.sdc.be.model.DataTypeDefinition;
43 import org.openecomp.sdc.be.model.InputDefinition;
44 import org.openecomp.sdc.be.model.PropertyDefinition;
45 import org.openecomp.sdc.be.model.ToscaPropertyData;
46 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
47 import org.openecomp.sdc.be.model.dto.FilterConstraintDto;
48 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
49 import org.openecomp.sdc.be.model.tosca.validators.DataTypeValidatorConverter;
50 import org.openecomp.sdc.be.model.validation.FilterConstraintValidator;
51 import org.openecomp.sdc.exception.ResponseFormat;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
54 import org.springframework.beans.factory.annotation.Autowired;
56 @org.springframework.stereotype.Component("NodeFilterValidator")
57 public class NodeFilterValidator {
59 private static final Logger LOGGER = LoggerFactory.getLogger(NodeFilterValidator.class);
60 private static final String SOURCE = "Source";
61 private static final String TARGET = "Target";
62 private static final String INPUT_NOT_FOUND_LOG = "Input '{}' not found in parent component '{}', unique id '{}'";
63 private static final Set<String> TYPES_WITH_SCHEMA = Set.of(ToscaPropertyType.MAP.getType(), ToscaPropertyType.LIST.getType());
64 private static final Set<String> COMPARABLE_TYPES = Set
65 .of(ToscaPropertyType.STRING.getType(), ToscaPropertyType.INTEGER.getType(), ToscaPropertyType.FLOAT.getType());
66 private final ComponentsUtils componentsUtils;
67 private final ApplicationDataTypeCache applicationDataTypeCache;
68 private final FilterConstraintValidator filterConstraintValidator;
71 public NodeFilterValidator(final ComponentsUtils componentsUtils, final ApplicationDataTypeCache applicationDataTypeCache,
72 final FilterConstraintValidator filterConstraintValidator) {
73 this.componentsUtils = componentsUtils;
74 this.applicationDataTypeCache = applicationDataTypeCache;
75 this.filterConstraintValidator = filterConstraintValidator;
78 public Either<Boolean, ResponseFormat> validateComponentInstanceExist(final Component component, final String componentInstanceId) {
79 if (component == null || StringUtils.isEmpty(componentInstanceId)) {
80 LOGGER.error("Expecting a component and a component instance id, given was '{}' and '{}'", component, componentInstanceId);
81 final String componentName = component == null ? "?" : component.getName();
82 return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND, componentName, componentInstanceId));
84 if (CollectionUtils.isEmpty(component.getComponentInstances()) || component.getComponentInstances().stream()
85 .noneMatch(ci -> ci.getUniqueId().equals(componentInstanceId))) {
86 LOGGER.error("Component '{}' node instance list is empty or component instance '{}' not found",
87 component.getUniqueId(), componentInstanceId);
88 return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND,
89 component.getName(), componentInstanceId));
91 return Either.left(Boolean.TRUE);
94 public Either<Boolean, ResponseFormat> validateFilter(final Component parentComponent, final String componentInstanceId,
95 final List<FilterConstraintDto> filterConstraint) {
96 if (CollectionUtils.isEmpty(filterConstraint)) {
97 return Either.left(true);
99 for (final FilterConstraintDto filterConstraintDto : filterConstraint) {
100 final Either<Boolean, ResponseFormat> validationEither =
101 validateFilter(parentComponent, componentInstanceId, filterConstraintDto);
102 if (validationEither.isRight()) {
103 return validationEither;
106 return Either.left(true);
108 public Either<Boolean, ResponseFormat> validateFilter(final Component parentComponent, final String componentInstanceId,
109 final FilterConstraintDto filterConstraint) {
110 validateFilterConstraint(filterConstraint);
111 switch (filterConstraint.getValueType()) {
113 if (filterConstraint.isCapabilityPropertyFilter()) {
114 return validateStaticValueAndOperatorOfCapabilityProperties(parentComponent, componentInstanceId, filterConstraint);
116 return validateStaticValueAndOperator(parentComponent, componentInstanceId, filterConstraint);
119 return validatePropertyConstraint(parentComponent, componentInstanceId, filterConstraint, filterConstraint.getCapabilityName());
121 return validateInputConstraint(parentComponent, componentInstanceId, filterConstraint);
123 return Either.left(true);
127 private void validateFilterConstraint(final FilterConstraintDto filterConstraint) {
128 filterConstraintValidator.validate(filterConstraint);
131 private Either<Boolean, ResponseFormat> validatePropertyConstraint(final Component parentComponent, final String componentInstanceId,
132 final FilterConstraintDto filterConstraint, final String capabilityName) {
133 String source = SOURCE;
134 final ToscaGetFunctionDataDefinition toscaGetFunction = filterConstraint.getAsToscaGetFunction().orElse(null);
135 if (toscaGetFunction == null || !(filterConstraint.getValue() instanceof ToscaGetFunctionDataDefinition)) {
136 return Either.right(componentsUtils.getResponseFormat(ActionStatus.TOSCA_FUNCTION_EXPECTED_ERROR));
138 final Optional<? extends ToscaPropertyData> sourceSelectedProperty = findPropertyFromGetFunction(parentComponent, toscaGetFunction);
139 if (sourceSelectedProperty.isPresent()) {
140 Optional<? extends PropertyDefinition> targetComponentInstanceProperty =
141 getInstanceProperties(parentComponent, componentInstanceId, capabilityName, filterConstraint.getPropertyName());
143 source = targetComponentInstanceProperty.isEmpty() ? TARGET : SOURCE;
144 if (targetComponentInstanceProperty.isPresent()) {
145 final ResponseFormat responseFormat = validatePropertyData(sourceSelectedProperty.get(), targetComponentInstanceProperty.get());
146 if (responseFormat != null) {
147 return Either.right(responseFormat);
149 return Either.left(true);
152 final String missingProperty = SOURCE.equals(source) ? filterConstraint.getValue().toString() : filterConstraint.getPropertyName();
153 return Either.right(componentsUtils.getResponseFormat(ActionStatus.FILTER_PROPERTY_NOT_FOUND, source, missingProperty));
156 private Optional<? extends ToscaPropertyData> findPropertyFromGetFunction(final Component parentComponent,
157 final ToscaGetFunctionDataDefinition toscaGetFunction) {
158 List<? extends ToscaPropertyData> sourcePropertyDefinitions;
159 if (PropertySource.SELF == toscaGetFunction.getPropertySource()) {
160 sourcePropertyDefinitions = getSelfPropertyFromGetFunction(parentComponent, toscaGetFunction);
162 sourcePropertyDefinitions = getInstancePropertiesBasedOnGetFunctionSource(parentComponent, toscaGetFunction);
164 final List<String> propertyPath = toscaGetFunction.getPropertyPathFromSource();
165 final Optional<? extends ToscaPropertyData> sourceProperty = sourcePropertyDefinitions.stream()
166 .filter(propertyDefinition -> propertyDefinition.getName().equals(propertyPath.get(0))).findFirst();
167 if (sourceProperty.isEmpty() || propertyPath.size() == 1) {
168 return sourceProperty;
170 final Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> allDataTypesEither =
171 applicationDataTypeCache.getAll(parentComponent.getModel());
172 if (allDataTypesEither.isRight()) {
173 return Optional.empty();
175 return findSubProperty(propertyPath.subList(1, propertyPath.size()), sourceProperty.get().getType(), allDataTypesEither.left().value());
178 private List<? extends ToscaPropertyData> getInstancePropertiesBasedOnGetFunctionSource(final Component parentComponent,
179 final ToscaGetFunctionDataDefinition toscaGetFunction) {
180 final ComponentInstance componentInstance = parentComponent.getComponentInstances().stream()
181 .filter(componentInstance1 -> componentInstance1.getName().equals(toscaGetFunction.getSourceName()))
184 if (componentInstance == null) {
187 final List<? extends ToscaPropertyData> instanceProperties;
188 switch (toscaGetFunction.getFunctionType()) {
190 instanceProperties = parentComponent.getComponentInstancesProperties().get(componentInstance.getUniqueId());
193 instanceProperties = parentComponent.getComponentInstancesAttributes().get(componentInstance.getUniqueId());
196 instanceProperties = List.of();
198 if (instanceProperties == null) {
201 return instanceProperties;
204 private static List<? extends ToscaPropertyData> getSelfPropertyFromGetFunction(final Component component,
205 final ToscaGetFunctionDataDefinition toscaGetFunction) {
206 switch (toscaGetFunction.getFunctionType()) {
208 if (component.getInputs() != null) {
209 return component.getInputs();
213 if (component.getProperties() != null) {
214 return component.getProperties();
218 if (component.getAttributes() != null) {
219 return component.getAttributes();
226 private Optional<PropertyDefinition> findSubProperty(final List<String> propertyPath, final String parentPropertyType,
227 final Map<String, DataTypeDefinition> modelDataTypes) {
228 final DataTypeDefinition dataTypeDefinition = modelDataTypes.get(parentPropertyType);
229 if (CollectionUtils.isEmpty(dataTypeDefinition.getProperties())) {
230 return Optional.empty();
232 final PropertyDefinition propertyDefinition = dataTypeDefinition.getProperties().stream()
233 .filter(propertyDefinition1 -> propertyDefinition1.getName().equals(propertyPath.get(0))).findFirst().orElse(null);
234 if (propertyDefinition == null) {
235 return Optional.empty();
237 if (propertyPath.size() == 1) {
238 return Optional.of(propertyDefinition);
240 return findSubProperty(propertyPath.subList(1, propertyPath.size()), propertyDefinition.getType(), modelDataTypes);
243 private Optional<ComponentInstanceProperty> getInstanceProperties(final Component parentComponent, final String componentInstanceId,
244 final String capabilityName, final String propertyName) {
245 if (StringUtils.isEmpty(capabilityName)) {
246 return parentComponent.getComponentInstancesProperties().get(componentInstanceId).stream()
247 .filter(property -> propertyName.equals(property.getName())).findFirst();
249 final Optional<ComponentInstance> componentInstanceOptional = parentComponent.getComponentInstances().stream()
250 .filter(componentInstance -> componentInstance.getUniqueId().equals(componentInstanceId)).findAny();
251 if (componentInstanceOptional.isPresent()) {
252 for (final List<CapabilityDefinition> listOfCaps : componentInstanceOptional.get().getCapabilities().values()) {
253 final Optional<CapabilityDefinition> capDef = listOfCaps.stream().filter(cap -> cap.getName().equals(capabilityName)).findAny();
254 if (capDef.isPresent()) {
255 return capDef.get().getProperties().stream().filter(property -> propertyName.equals(property.getName())).findFirst();
260 return Optional.empty();
263 private Either<Boolean, ResponseFormat> validateInputConstraint(final Component parentComponent, final String componentInstanceId,
264 final FilterConstraintDto filterConstraint) {
265 final List<InputDefinition> sourceInputDefinition = parentComponent.getInputs();
266 if (CollectionUtils.isEmpty(sourceInputDefinition)) {
267 LOGGER.debug("Parent component '{}', unique id '{}', does not have inputs", parentComponent.getName(), parentComponent.getUniqueId());
268 return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_DOES_NOT_HAVE_INPUTS, parentComponent.getName()));
270 if (!(filterConstraint.getValue() instanceof ToscaGetFunctionDataDefinition)) {
271 return Either.right(componentsUtils.getResponseFormat(ActionStatus.TOSCA_FUNCTION_EXPECTED_ERROR));
273 final ToscaGetFunctionDataDefinition getFunction = (ToscaGetFunctionDataDefinition) filterConstraint.getValue();
274 final List<String> propertyPathFromSource = getFunction.getPropertyPathFromSource();
275 Optional<? extends PropertyDefinition> sourceSelectedProperty =
276 sourceInputDefinition.stream().filter(input -> input.getName().equals(propertyPathFromSource.get(0))).findFirst();
277 if (sourceSelectedProperty.isEmpty()) {
278 LOGGER.debug(INPUT_NOT_FOUND_LOG,
279 propertyPathFromSource.get(0), parentComponent.getName(), parentComponent.getUniqueId());
281 componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INPUT_NOT_FOUND, propertyPathFromSource.get(0), parentComponent.getName())
284 if (propertyPathFromSource.size() > 1) {
285 final Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> allDataTypesEither =
286 applicationDataTypeCache.getAll(parentComponent.getModel());
287 if (allDataTypesEither.isRight()) {
288 LOGGER.error("Could not load data types for model {}", parentComponent.getModel());
289 return Either.right(componentsUtils.getResponseFormat(ActionStatus.DATA_TYPES_NOT_LOADED, parentComponent.getModel()));
291 sourceSelectedProperty =
292 findSubProperty(propertyPathFromSource.subList(1, propertyPathFromSource.size()), sourceSelectedProperty.get().getType(),
293 allDataTypesEither.left().value());
295 final Optional<? extends PropertyDefinition> targetComponentInstanceProperty;
296 if (PropertyFilterTargetType.CAPABILITY.equals(filterConstraint.getTargetType())) {
297 final CapabilityDefinition capability = parentComponent.getComponentInstances().stream()
298 .filter(componentInstance -> componentInstance.getUniqueId().equals(componentInstanceId))
299 .map(componentInstance -> componentInstance.getCapabilities().values())
300 .flatMap(Collection::stream)
301 .flatMap(Collection::stream)
302 .filter(capabilityDefinition -> capabilityDefinition.getName().equals(filterConstraint.getCapabilityName()))
303 .findFirst().orElse(null);
304 if (capability == null) {
306 componentsUtils.getResponseFormat(ActionStatus.CAPABILITY_NOT_FOUND_IN_COMPONENT,
307 filterConstraint.getCapabilityName(), parentComponent.getComponentType().getValue(), parentComponent.getName())
310 targetComponentInstanceProperty = capability.getProperties().stream()
311 .filter(property -> filterConstraint.getPropertyName().equals(property.getName()))
314 targetComponentInstanceProperty =
315 parentComponent.getComponentInstancesProperties()
316 .get(componentInstanceId).stream()
317 .filter(property -> filterConstraint.getPropertyName().equals(property.getName()))
320 if (sourceSelectedProperty.isPresent() && targetComponentInstanceProperty.isPresent()) {
321 final ResponseFormat responseFormat = validatePropertyData(sourceSelectedProperty.get(), targetComponentInstanceProperty.get());
322 if (responseFormat != null) {
323 return Either.right(responseFormat);
325 return Either.left(true);
328 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INPUTS_NOT_FOUND));
331 private <T extends ToscaPropertyData> ResponseFormat validatePropertyData(final T sourcePropDefinition,
332 final T targetPropDefinition) {
333 final String sourceType = sourcePropDefinition.getType();
334 final String targetType = targetPropDefinition.getType();
335 if (sourceType.equals(targetType)) {
336 if (TYPES_WITH_SCHEMA.contains(sourceType)) {
337 final String sourceSchemaType = sourcePropDefinition.getSchemaType();
338 final String targetSchemaType = targetPropDefinition.getSchemaType();
339 if (sourceSchemaType != null && !sourceSchemaType.equals(targetSchemaType)) {
340 return componentsUtils.getResponseFormat(ActionStatus.SOURCE_TARGET_SCHEMA_MISMATCH,
341 targetPropDefinition.getName(), targetSchemaType, sourcePropDefinition.getName(), sourceSchemaType);
346 return componentsUtils.getResponseFormat(ActionStatus.SOURCE_TARGET_PROPERTY_TYPE_MISMATCH,
347 sourcePropDefinition.getName(), sourcePropDefinition.getType(), targetPropDefinition.getName(), targetPropDefinition.getType());
350 private Either<Boolean, ResponseFormat> validateStaticValueAndOperator(final Component parentComponent, final String componentInstanceId,
351 final FilterConstraintDto filterConstraint) {
352 final ComponentInstanceProperty componentInstanceProperty = parentComponent.getComponentInstancesProperties()
353 .get(componentInstanceId).stream().filter(property -> filterConstraint.getPropertyName().equals(property.getName()))
356 if (componentInstanceProperty == null) {
357 return Either.right(componentsUtils.getResponseFormat(ActionStatus.SELECTED_PROPERTY_NOT_PRESENT, filterConstraint.getPropertyName()));
359 if (filterConstraint.getOperator().isComparable() && !COMPARABLE_TYPES.contains(componentInstanceProperty.getType())) {
360 return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_OPERATOR_PROVIDED, filterConstraint.getPropertyName(),
361 filterConstraint.getOperator().getType()));
363 return isValidValueCheck(componentInstanceProperty.getType(), componentInstanceProperty.getSchemaType(), parentComponent.getModel(),
364 filterConstraint.getValue(), filterConstraint.getPropertyName());
367 private Either<Boolean, ResponseFormat> validateStaticSubstitutionFilter(final Component component,
368 final FilterConstraintDto filterConstraint) {
370 final PropertyDefinition componentProperty = component.getProperties().stream()
371 .filter(property -> property.getName().equals(filterConstraint.getPropertyName())).findFirst().orElse(null);
372 if (componentProperty == null) {
373 return Either.right(componentsUtils.getResponseFormat(ActionStatus.SELECTED_PROPERTY_NOT_PRESENT, filterConstraint.getPropertyName()));
375 if (filterConstraint.getOperator().isComparable() && !COMPARABLE_TYPES.contains(componentProperty.getType())) {
376 return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_OPERATOR_PROVIDED, filterConstraint.getPropertyName(),
377 filterConstraint.getOperator().getType()));
379 return isValidValueCheck(componentProperty.getType(), componentProperty.getSchemaType(), component.getModel(),
380 filterConstraint.getValue(), filterConstraint.getPropertyName());
383 private Either<Boolean, ResponseFormat> validateStaticValueAndOperatorOfCapabilityProperties(final Component parentComponent,
384 final String componentInstanceId,
385 final FilterConstraintDto filterConstraint) {
386 ComponentInstanceProperty componentInstanceProperty = null;
387 final Optional<ComponentInstance> optionalComponentInstances = parentComponent.getComponentInstances().stream()
388 .filter(componentInstance -> componentInstanceId.equalsIgnoreCase(componentInstance.getUniqueId())).findFirst();
389 if (optionalComponentInstances.isPresent()) {
390 final Optional<List<CapabilityDefinition>> optionalCapabilityDefinitionList = optionalComponentInstances.get().getCapabilities().values()
391 .stream().filter(capabilityDefinitions -> capabilityDefinitions.stream()
392 .allMatch(capabilityDefinition -> capabilityDefinition.getProperties() != null)).collect(Collectors.toList()).stream().filter(
393 capabilityDefinitions -> capabilityDefinitions.stream().allMatch(
394 capabilityDefinition -> capabilityDefinition.getProperties().stream().anyMatch(
395 componentInstanceProperty1 -> filterConstraint.getPropertyName()
396 .equalsIgnoreCase(componentInstanceProperty1.getName())))).findFirst();
397 if (optionalCapabilityDefinitionList.isPresent() && !optionalCapabilityDefinitionList.get().isEmpty()) {
398 componentInstanceProperty =
399 getComponentInstanceProperty(optionalCapabilityDefinitionList.get().get(0), filterConstraint.getPropertyName()).orElse(null);
403 if (componentInstanceProperty == null) {
404 return Either.right(componentsUtils.getResponseFormat(ActionStatus.SELECTED_PROPERTY_NOT_PRESENT, filterConstraint.getPropertyName()));
406 if (filterConstraint.getOperator().isComparable() && !COMPARABLE_TYPES.contains(componentInstanceProperty.getType())) {
407 return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_OPERATOR_PROVIDED, filterConstraint.getPropertyName(),
408 filterConstraint.getOperator().getType()));
410 return isValidValueCheck(componentInstanceProperty.getType(), componentInstanceProperty.getSchemaType(), parentComponent.getModel(),
411 filterConstraint.getValue(), filterConstraint.getPropertyName());
414 private Optional<ComponentInstanceProperty> getComponentInstanceProperty(CapabilityDefinition capabilityDefinition, final String propertyName){
415 return capabilityDefinition.getProperties().stream().filter(property -> property.getName().equals(propertyName)).findAny();
418 private Either<Boolean, ResponseFormat> isValidValueCheck(final String type, final String schemaType, final String model,
419 final Object value, final String propertyName) {
420 final Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> allDataTypesEither =
421 applicationDataTypeCache.getAll(model);
422 if (allDataTypesEither.isRight()) {
423 LOGGER.error("Could not validate filter value. Could not load data types for model {}", model);
424 return Either.right(componentsUtils.getResponseFormat(ActionStatus.DATA_TYPES_NOT_LOADED, model));
426 final Map<String, DataTypeDefinition> modelDataTypesMap = allDataTypesEither.left().value();
427 final ToscaPropertyType toscaPropertyType = ToscaPropertyType.isValidType(type);
428 if (toscaPropertyType == null && !modelDataTypesMap.containsKey(type)) {
429 return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_PROPERTY_TYPE, type, propertyName));
431 final String valueAsJsonString;
433 valueAsJsonString = new Gson().toJson(value);
434 } catch (final Exception e) {
435 LOGGER.debug("Unsupported property filter value", e);
436 return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_VALUE_PROVIDED, type, propertyName, String.valueOf(value)));
438 if (toscaPropertyType != null) {
439 if (toscaPropertyType.getValidator().isValid(valueAsJsonString, schemaType, modelDataTypesMap)) {
440 return Either.left(true);
443 if (DataTypeValidatorConverter.getInstance().isValid(valueAsJsonString, modelDataTypesMap.get(type), modelDataTypesMap)) {
444 return Either.left(true);
448 return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_VALUE_PROVIDED, type, propertyName, valueAsJsonString));
451 public Either<Boolean, ResponseFormat> validateSubstitutionFilter(final Component component, final List<FilterConstraintDto> filterConstraintList) {
452 if (CollectionUtils.isEmpty(filterConstraintList)) {
453 return Either.right(componentsUtils.getResponseFormat(ActionStatus.CONSTRAINT_FORMAT_INCORRECT));
455 for (final FilterConstraintDto filterConstraintDto : filterConstraintList) {
456 final Either<Boolean, ResponseFormat> validationEither = validateSubstitutionFilter(component, filterConstraintDto);
457 if (validationEither.isRight()) {
458 return validationEither;
461 return Either.left(true);
464 public Either<Boolean, ResponseFormat> validateSubstitutionFilter(final Component component, final FilterConstraintDto filterConstraint) {
465 validateFilterConstraint(filterConstraint);
466 switch (filterConstraint.getValueType()) {
468 return validateStaticSubstitutionFilter(component, filterConstraint);
472 return validateSubstitutionFilterGetFunctionConstraint(component, filterConstraint);
474 return Either.left(true);
478 private Either<Boolean, ResponseFormat> validateSubstitutionFilterGetFunctionConstraint(final Component component,
479 final FilterConstraintDto filterConstraint) {
480 final ToscaGetFunctionDataDefinition toscaGetFunction = filterConstraint.getAsToscaGetFunction().orElse(null);
481 if (toscaGetFunction == null) {
482 return Either.right(componentsUtils.getResponseFormat(ActionStatus.TOSCA_FUNCTION_EXPECTED_ERROR));
485 if (CollectionUtils.isEmpty(component.getProperties())) {
487 componentsUtils.getResponseFormat(ActionStatus.FILTER_PROPERTY_NOT_FOUND, TARGET, getPropertyType(toscaGetFunction),
488 filterConstraint.getPropertyName())
492 final Optional<? extends PropertyDefinition> targetComponentProperty = component.getProperties().stream()
493 .filter(property -> property.getName().equals(filterConstraint.getPropertyName())).findFirst();
494 if (targetComponentProperty.isEmpty()) {
496 componentsUtils.getResponseFormat(ActionStatus.FILTER_PROPERTY_NOT_FOUND, TARGET, getPropertyType(toscaGetFunction),
497 filterConstraint.getPropertyName())
501 final Optional<? extends ToscaPropertyData> sourceSelectedProperty = findPropertyFromGetFunction(component, toscaGetFunction);
502 if (sourceSelectedProperty.isEmpty()) {
503 return Either.right(componentsUtils.getResponseFormat(ActionStatus.FILTER_PROPERTY_NOT_FOUND, SOURCE, getPropertyType(toscaGetFunction),
504 String.join("->", toscaGetFunction.getPropertyPathFromSource())));
507 final ResponseFormat responseFormat = validatePropertyData(sourceSelectedProperty.get(), targetComponentProperty.get());
508 if (responseFormat != null) {
509 return Either.right(responseFormat);
511 return Either.left(true);
514 private String getPropertyType(final ToscaGetFunctionDataDefinition toscaGetFunction) {
515 switch (toscaGetFunction.getType()) {