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.ArrayList;
25 import java.util.Collection;
26 import java.util.List;
28 import java.util.Optional;
30 import java.util.stream.Collectors;
31 import org.apache.commons.collections4.CollectionUtils;
32 import org.apache.commons.lang3.StringUtils;
33 import org.openecomp.sdc.be.dao.api.ActionStatus;
34 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
35 import org.openecomp.sdc.be.datatypes.elements.ToscaGetFunctionDataDefinition;
36 import org.openecomp.sdc.be.datatypes.enums.ConstraintType;
37 import org.openecomp.sdc.be.datatypes.enums.PropertyFilterTargetType;
38 import org.openecomp.sdc.be.datatypes.enums.PropertySource;
39 import org.openecomp.sdc.be.impl.ComponentsUtils;
40 import org.openecomp.sdc.be.model.CapabilityDefinition;
41 import org.openecomp.sdc.be.model.Component;
42 import org.openecomp.sdc.be.model.ComponentInstance;
43 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
44 import org.openecomp.sdc.be.model.DataTypeDefinition;
45 import org.openecomp.sdc.be.model.InputDefinition;
46 import org.openecomp.sdc.be.model.PropertyDefinition;
47 import org.openecomp.sdc.be.model.ToscaPropertyData;
48 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
49 import org.openecomp.sdc.be.model.dto.FilterConstraintDto;
50 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
51 import org.openecomp.sdc.be.model.tosca.validators.DataTypeValidatorConverter;
52 import org.openecomp.sdc.be.model.validation.FilterConstraintValidator;
53 import org.openecomp.sdc.exception.ResponseFormat;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
56 import org.springframework.beans.factory.annotation.Autowired;
58 @org.springframework.stereotype.Component("NodeFilterValidator")
59 public class NodeFilterValidator {
61 private static final Logger LOGGER = LoggerFactory.getLogger(NodeFilterValidator.class);
62 private static final String SOURCE = "Source";
63 private static final String TARGET = "Target";
64 private static final String INPUT_NOT_FOUND_LOG = "Input '{}' not found in parent component '{}', unique id '{}'";
65 private static final Set<String> TYPES_WITH_SCHEMA = Set.of(ToscaPropertyType.MAP.getType(), ToscaPropertyType.LIST.getType());
66 private static final Set<String> COMPARABLE_TYPES = Set.of(
67 ToscaPropertyType.SCALAR_UNIT_SIZE.getType(),
68 ToscaPropertyType.SCALAR_UNIT_TIME.getType(),
69 ToscaPropertyType.SCALAR_UNIT_BITRATE.getType(),
70 ToscaPropertyType.SCALAR_UNIT_FREQUENCY.getType(),
71 ToscaPropertyType.BOOLEAN.getType(),
72 ToscaPropertyType.STRING.getType(),
73 ToscaPropertyType.INTEGER.getType(),
74 ToscaPropertyType.FLOAT.getType());
75 private final ComponentsUtils componentsUtils;
76 private final ApplicationDataTypeCache applicationDataTypeCache;
77 private final FilterConstraintValidator filterConstraintValidator;
80 public NodeFilterValidator(final ComponentsUtils componentsUtils, final ApplicationDataTypeCache applicationDataTypeCache,
81 final FilterConstraintValidator filterConstraintValidator) {
82 this.componentsUtils = componentsUtils;
83 this.applicationDataTypeCache = applicationDataTypeCache;
84 this.filterConstraintValidator = filterConstraintValidator;
87 public Either<Boolean, ResponseFormat> validateComponentInstanceExist(final Component component, final String componentInstanceId) {
88 if (component == null || StringUtils.isEmpty(componentInstanceId)) {
89 LOGGER.error("Expecting a component and a component instance id, given was '{}' and '{}'", component, componentInstanceId);
90 final String componentName = component == null ? "?" : component.getName();
91 return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND, componentName, componentInstanceId));
93 if (CollectionUtils.isEmpty(component.getComponentInstances()) || component.getComponentInstances().stream()
94 .noneMatch(ci -> ci.getUniqueId().equals(componentInstanceId))) {
95 LOGGER.error("Component '{}' node instance list is empty or component instance '{}' not found",
96 component.getUniqueId(), componentInstanceId);
97 return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND,
98 component.getName(), componentInstanceId));
100 return Either.left(Boolean.TRUE);
103 public Either<Boolean, ResponseFormat> validateFilter(final Component parentComponent, final String componentInstanceId,
104 final List<FilterConstraintDto> filterConstraint) {
105 if (CollectionUtils.isEmpty(filterConstraint)) {
106 return Either.left(true);
108 for (final FilterConstraintDto filterConstraintDto : filterConstraint) {
109 final Either<Boolean, ResponseFormat> validationEither =
110 validateFilter(parentComponent, componentInstanceId, filterConstraintDto);
111 if (validationEither.isRight()) {
112 return validationEither;
115 return Either.left(true);
118 public Either<Boolean, ResponseFormat> validateFilter(final Component parentComponent, final String componentInstanceId,
119 final FilterConstraintDto filterConstraint) {
120 validateFilterConstraint(filterConstraint);
121 switch (filterConstraint.getValueType()) {
123 if (filterConstraint.isCapabilityPropertyFilter()) {
124 return validateStaticValueAndOperatorOfCapabilityProperties(parentComponent, componentInstanceId, filterConstraint);
126 return validateStaticValueAndOperator(parentComponent, componentInstanceId, filterConstraint);
129 return validatePropertyConstraint(parentComponent, componentInstanceId, filterConstraint, filterConstraint.getCapabilityName());
131 return validateInputConstraint(parentComponent, componentInstanceId, filterConstraint);
133 return Either.left(true);
137 private void validateFilterConstraint(final FilterConstraintDto filterConstraint) {
138 filterConstraintValidator.validate(filterConstraint);
141 private Either<Boolean, ResponseFormat> validatePropertyConstraint(final Component parentComponent, final String componentInstanceId,
142 final FilterConstraintDto filterConstraint, final String capabilityName) {
143 String source = SOURCE;
144 ResponseFormat responseFormat = null;
145 List<ToscaGetFunctionDataDefinition> toscaGetFunctionDataDefinitionList = new ArrayList<>();
146 final ToscaGetFunctionDataDefinition toscaGetFunction = filterConstraint.getAsToscaGetFunction().orElse(null);
147 if (toscaGetFunction == null || !(filterConstraint.getValue() instanceof ToscaGetFunctionDataDefinition)) {
148 final List<ToscaGetFunctionDataDefinition> toscaGetFunctionList = filterConstraint.getAsListToscaGetFunction().orElse(null);
149 if (toscaGetFunctionList == null || toscaGetFunctionList.isEmpty() || !(filterConstraint.getValue() instanceof List)) {
150 return Either.right(componentsUtils.getResponseFormat(ActionStatus.TOSCA_FUNCTION_EXPECTED_ERROR));
153 toscaGetFunctionDataDefinitionList = toscaGetFunctionList;
157 toscaGetFunctionDataDefinitionList.add(toscaGetFunction);
159 Boolean allGood = true;
160 for (ToscaGetFunctionDataDefinition _toscaGetFunction: toscaGetFunctionDataDefinitionList) {
162 final Optional<? extends ToscaPropertyData> sourceSelectedProperty =
163 findPropertyFromGetFunction(parentComponent, _toscaGetFunction);
164 if (sourceSelectedProperty.isPresent()) {
165 Optional<? extends PropertyDefinition> targetComponentInstanceProperty =
166 getInstanceProperties(parentComponent, componentInstanceId, capabilityName,
167 filterConstraint.getPropertyName());
169 source = targetComponentInstanceProperty.isEmpty() ? TARGET : SOURCE;
170 if (targetComponentInstanceProperty.isPresent()) {
172 validatePropertyData(sourceSelectedProperty.get(), targetComponentInstanceProperty.get(),
173 filterConstraint.getOperator().isLengthConstraint());
174 if (responseFormat != null) {
182 final String missingProperty =
183 SOURCE.equals(source) ? filterConstraint.getValue().toString() : filterConstraint.getPropertyName();
185 componentsUtils.getResponseFormat(ActionStatus.FILTER_PROPERTY_NOT_FOUND, source, missingProperty);
191 final String missingProperty =
192 SOURCE.equals(source) ? filterConstraint.getValue().toString() : filterConstraint.getPropertyName();
194 componentsUtils.getResponseFormat(ActionStatus.FILTER_PROPERTY_NOT_FOUND, source, missingProperty);
199 return Either.left(true);
201 return Either.right(responseFormat);
204 private Optional<? extends ToscaPropertyData> findPropertyFromGetFunction(final Component parentComponent,
205 final ToscaGetFunctionDataDefinition toscaGetFunction) {
206 List<? extends ToscaPropertyData> sourcePropertyDefinitions;
207 if (PropertySource.SELF == toscaGetFunction.getPropertySource()) {
208 sourcePropertyDefinitions = getSelfPropertyFromGetFunction(parentComponent, toscaGetFunction);
210 sourcePropertyDefinitions = getInstancePropertiesBasedOnGetFunctionSource(parentComponent, toscaGetFunction);
212 final List<String> propertyPath = toscaGetFunction.getPropertyPathFromSource();
213 final Optional<? extends ToscaPropertyData> sourceProperty = sourcePropertyDefinitions.stream()
214 .filter(propertyDefinition -> propertyDefinition.getName().equals(propertyPath.get(0))).findFirst();
215 if (sourceProperty.isEmpty() || propertyPath.size() == 1) {
216 return sourceProperty;
218 final Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> allDataTypesEither =
219 applicationDataTypeCache.getAll(parentComponent.getModel());
220 if (allDataTypesEither.isRight()) {
221 return Optional.empty();
223 return findSubProperty(propertyPath.subList(1, propertyPath.size()), sourceProperty.get().getType(), allDataTypesEither.left().value());
226 private List<? extends ToscaPropertyData> getInstancePropertiesBasedOnGetFunctionSource(final Component parentComponent,
227 final ToscaGetFunctionDataDefinition toscaGetFunction) {
228 final ComponentInstance componentInstance = parentComponent.getComponentInstances().stream()
229 .filter(componentInstance1 -> componentInstance1.getName().equals(toscaGetFunction.getSourceName()))
232 if (componentInstance == null) {
235 final List<? extends ToscaPropertyData> instanceProperties;
236 switch (toscaGetFunction.getFunctionType()) {
238 instanceProperties = parentComponent.getComponentInstancesProperties().get(componentInstance.getUniqueId());
241 instanceProperties = parentComponent.getComponentInstancesAttributes().get(componentInstance.getUniqueId());
244 instanceProperties = List.of();
246 if (instanceProperties == null) {
249 return instanceProperties;
252 private static List<? extends ToscaPropertyData> getSelfPropertyFromGetFunction(final Component component,
253 final ToscaGetFunctionDataDefinition toscaGetFunction) {
254 switch (toscaGetFunction.getFunctionType()) {
256 if (component.getInputs() != null) {
257 return component.getInputs();
261 if (component.getProperties() != null) {
262 return component.getProperties();
266 if (component.getAttributes() != null) {
267 return component.getAttributes();
274 private Optional<PropertyDefinition> findSubProperty(final List<String> propertyPath, final String parentPropertyType,
275 final Map<String, DataTypeDefinition> modelDataTypes) {
276 final DataTypeDefinition dataTypeDefinition = modelDataTypes.get(parentPropertyType);
277 if (CollectionUtils.isEmpty(dataTypeDefinition.getProperties())) {
278 return Optional.empty();
280 final PropertyDefinition propertyDefinition = dataTypeDefinition.getProperties().stream()
281 .filter(propertyDefinition1 -> propertyDefinition1.getName().equals(propertyPath.get(0))).findFirst().orElse(null);
282 if (propertyDefinition == null) {
283 return Optional.empty();
285 if (propertyPath.size() == 1) {
286 return Optional.of(propertyDefinition);
288 return findSubProperty(propertyPath.subList(1, propertyPath.size()), propertyDefinition.getType(), modelDataTypes);
291 private Optional<ComponentInstanceProperty> getInstanceProperties(final Component parentComponent, final String componentInstanceId,
292 final String capabilityName, final String propertyName) {
293 if (StringUtils.isEmpty(capabilityName)) {
294 return parentComponent.getComponentInstancesProperties().get(componentInstanceId).stream()
295 .filter(property -> propertyName.equals(property.getName())).findFirst();
297 final Optional<ComponentInstance> componentInstanceOptional = parentComponent.getComponentInstances().stream()
298 .filter(componentInstance -> componentInstance.getUniqueId().equals(componentInstanceId)).findAny();
299 if (componentInstanceOptional.isPresent()) {
300 for (final List<CapabilityDefinition> listOfCaps : componentInstanceOptional.get().getCapabilities().values()) {
301 final Optional<CapabilityDefinition> capDef = listOfCaps.stream().filter(cap -> cap.getName().equals(capabilityName)).findAny();
302 if (capDef.isPresent()) {
303 return capDef.get().getProperties().stream().filter(property -> propertyName.equals(property.getName())).findFirst();
308 return Optional.empty();
311 private Either<Boolean, ResponseFormat> validateInputConstraint(final Component parentComponent, final String componentInstanceId,
312 final FilterConstraintDto filterConstraint) {
313 final List<InputDefinition> sourceInputDefinition = parentComponent.getInputs();
314 if (CollectionUtils.isEmpty(sourceInputDefinition)) {
315 LOGGER.debug("Parent component '{}', unique id '{}', does not have inputs", parentComponent.getName(), parentComponent.getUniqueId());
316 return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_DOES_NOT_HAVE_INPUTS, parentComponent.getName()));
318 if (!(filterConstraint.getValue() instanceof ToscaGetFunctionDataDefinition)) {
319 if (filterConstraint.getValue() instanceof List) {
320 Optional optValid = ((List<?>) filterConstraint.getValue()).stream().filter(filterConstraintValue ->
321 !(filterConstraintValue instanceof ToscaGetFunctionDataDefinition)).findAny();
322 if (optValid.isPresent()) {
323 return Either.right(componentsUtils.getResponseFormat(ActionStatus.TOSCA_FUNCTION_EXPECTED_ERROR));
327 return Either.right(componentsUtils.getResponseFormat(ActionStatus.TOSCA_FUNCTION_EXPECTED_ERROR));
330 if (filterConstraint.getValue() instanceof ToscaGetFunctionDataDefinition) {
331 final ToscaGetFunctionDataDefinition getFunction =
332 (ToscaGetFunctionDataDefinition) filterConstraint.getValue();
333 final List<String> propertyPathFromSource = getFunction.getPropertyPathFromSource();
334 Optional<? extends PropertyDefinition> sourceSelectedProperty =
335 sourceInputDefinition.stream().filter(input -> input.getName().equals(propertyPathFromSource.get(0)))
337 if (sourceSelectedProperty.isEmpty()) {
338 LOGGER.debug(INPUT_NOT_FOUND_LOG,
339 propertyPathFromSource.get(0), parentComponent.getName(), parentComponent.getUniqueId());
341 componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INPUT_NOT_FOUND,
342 propertyPathFromSource.get(0), parentComponent.getName())
345 if (propertyPathFromSource.size() > 1) {
346 final Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> allDataTypesEither =
347 applicationDataTypeCache.getAll(parentComponent.getModel());
348 if (allDataTypesEither.isRight()) {
349 LOGGER.error("Could not load data types for model {}", parentComponent.getModel());
350 return Either.right(componentsUtils.getResponseFormat(ActionStatus.DATA_TYPES_NOT_LOADED,
351 parentComponent.getModel()));
353 sourceSelectedProperty =
354 findSubProperty(propertyPathFromSource.subList(1, propertyPathFromSource.size()),
355 sourceSelectedProperty.get().getType(),
356 allDataTypesEither.left().value());
358 final Optional<? extends PropertyDefinition> targetComponentInstanceProperty;
359 if (PropertyFilterTargetType.CAPABILITY.equals(filterConstraint.getTargetType())) {
360 final CapabilityDefinition capability = parentComponent.getComponentInstances().stream()
361 .filter(componentInstance -> componentInstance.getUniqueId().equals(componentInstanceId))
362 .map(componentInstance -> componentInstance.getCapabilities().values())
363 .flatMap(Collection::stream)
364 .flatMap(Collection::stream)
365 .filter(capabilityDefinition -> capabilityDefinition.getName()
366 .equals(filterConstraint.getCapabilityName()))
367 .findFirst().orElse(null);
368 if (capability == null) {
370 componentsUtils.getResponseFormat(ActionStatus.CAPABILITY_NOT_FOUND_IN_COMPONENT,
371 filterConstraint.getCapabilityName(), parentComponent.getComponentType().getValue(),
372 parentComponent.getName())
375 targetComponentInstanceProperty = capability.getProperties().stream()
376 .filter(property -> filterConstraint.getPropertyName().equals(property.getName()))
379 targetComponentInstanceProperty =
380 parentComponent.getComponentInstancesProperties()
381 .get(componentInstanceId).stream()
382 .filter(property -> filterConstraint.getPropertyName().equals(property.getName()))
385 if (sourceSelectedProperty.isPresent() && targetComponentInstanceProperty.isPresent()) {
386 final ResponseFormat responseFormat =
387 validatePropertyData(sourceSelectedProperty.get(), targetComponentInstanceProperty.get(),
388 filterConstraint.getOperator().isLengthConstraint());
389 if (responseFormat != null) {
390 return Either.right(responseFormat);
392 return Either.left(true);
395 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INPUTS_NOT_FOUND));
397 return Either.left(true);
400 private <T extends ToscaPropertyData> ResponseFormat validatePropertyData(final T sourcePropDefinition,
401 final T targetPropDefinition,
402 final boolean isLengthConstraint) {
403 final String sourceType = sourcePropDefinition.getType();
404 final String targetType = targetPropDefinition.getType();
405 if (!isLengthConstraint) {
406 if (sourceType.equals(targetType)) {
407 if (TYPES_WITH_SCHEMA.contains(sourceType)) {
408 final String sourceSchemaType = sourcePropDefinition.getSchemaType();
409 final String targetSchemaType = targetPropDefinition.getSchemaType();
410 if (sourceSchemaType != null && !sourceSchemaType.equals(targetSchemaType)) {
411 return componentsUtils.getResponseFormat(ActionStatus.SOURCE_TARGET_SCHEMA_MISMATCH,
412 targetPropDefinition.getName(), targetSchemaType, sourcePropDefinition.getName(),
419 if (null != ((PropertyDefinition) sourcePropDefinition).getSchemaProperty()){
420 if (((PropertyDefinition) sourcePropDefinition).getSchemaProperty().getType().equals(targetType)) {
421 if (TYPES_WITH_SCHEMA.contains(((PropertyDefinition) sourcePropDefinition).getSchemaProperty().getType())) {
422 final String sourceSchemaType = sourcePropDefinition.getSchemaType();
423 final String targetSchemaType = targetPropDefinition.getSchemaType();
424 if (sourceSchemaType != null && !sourceSchemaType.equals(targetSchemaType)) {
425 return componentsUtils.getResponseFormat(ActionStatus.SOURCE_TARGET_SCHEMA_MISMATCH,
426 targetPropDefinition.getName(), targetSchemaType, sourcePropDefinition.getName(),
436 if (sourceType.equalsIgnoreCase("integer")) {
437 if (TYPES_WITH_SCHEMA.contains(sourceType)) {
438 final String sourceSchemaType = sourcePropDefinition.getSchemaType();
439 if (sourceSchemaType != null && !sourceSchemaType.equalsIgnoreCase("integer")) {
440 return componentsUtils.getResponseFormat(ActionStatus.SOURCE_TARGET_SCHEMA_MISMATCH,
441 targetPropDefinition.getName(), "integer", sourcePropDefinition.getName(),
448 return componentsUtils.getResponseFormat(ActionStatus.SOURCE_TARGET_PROPERTY_TYPE_MISMATCH,
449 sourcePropDefinition.getName(), sourcePropDefinition.getType(), targetPropDefinition.getName(), targetPropDefinition.getType());
452 private Either<Boolean, ResponseFormat> validateStaticValueAndOperator(final Component parentComponent, final String componentInstanceId,
453 final FilterConstraintDto filterConstraint) {
454 final ComponentInstanceProperty componentInstanceProperty = parentComponent.getComponentInstancesProperties()
455 .get(componentInstanceId).stream().filter(property -> filterConstraint.getPropertyName().equals(property.getName()))
458 if (componentInstanceProperty == null) {
459 return Either.right(componentsUtils.getResponseFormat(ActionStatus.SELECTED_PROPERTY_NOT_PRESENT, filterConstraint.getPropertyName()));
461 if (filterConstraint.getOperator().isComparable() && !TYPES_WITH_SCHEMA.contains(componentInstanceProperty.getType())
462 && !COMPARABLE_TYPES.contains(componentInstanceProperty.getType())) {
463 return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_OPERATOR_PROVIDED, filterConstraint.getPropertyName(),
464 filterConstraint.getOperator().getType()));
466 if (filterConstraint.getOperator().equals(ConstraintType.VALID_VALUES) || filterConstraint.getOperator().equals(ConstraintType.IN_RANGE)) {
467 return isValidValueCheck("list", componentInstanceProperty.getType(), parentComponent.getModel(),
468 filterConstraint.getValue(), filterConstraint.getPropertyName());
470 if (filterConstraint.getOperator().isLengthConstraint() && componentInstanceProperty.getType().equals("list")) {
471 return Either.left(true);
473 return isValidValueCheck(componentInstanceProperty.getType(), componentInstanceProperty.getSchemaType(), parentComponent.getModel(),
474 filterConstraint.getValue(), filterConstraint.getPropertyName());
477 private Either<Boolean, ResponseFormat> validateStaticSubstitutionFilter(final Component component,
478 final FilterConstraintDto filterConstraint) {
480 final PropertyDefinition componentProperty = component.getProperties().stream()
481 .filter(property -> property.getName().equals(filterConstraint.getPropertyName())).findFirst().orElse(null);
482 if (componentProperty == null) {
483 return Either.right(componentsUtils.getResponseFormat(ActionStatus.SELECTED_PROPERTY_NOT_PRESENT, filterConstraint.getPropertyName()));
485 if (filterConstraint.getOperator().isComparable() && !TYPES_WITH_SCHEMA.contains(componentProperty.getType())
486 && !COMPARABLE_TYPES.contains(componentProperty.getType())) {
487 return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_OPERATOR_PROVIDED, filterConstraint.getPropertyName(),
488 filterConstraint.getOperator().getType()));
490 if (filterConstraint.getOperator().equals(ConstraintType.VALID_VALUES) || filterConstraint.getOperator().equals(ConstraintType.IN_RANGE)) {
491 return isValidValueCheck("list", componentProperty.getType(), component.getModel(),
492 filterConstraint.getValue(), filterConstraint.getPropertyName());
494 return isValidValueCheck(componentProperty.getType(), componentProperty.getSchemaType(), component.getModel(),
495 filterConstraint.getValue(), filterConstraint.getPropertyName());
498 private Either<Boolean, ResponseFormat> validateStaticValueAndOperatorOfCapabilityProperties(final Component parentComponent,
499 final String componentInstanceId,
500 final FilterConstraintDto filterConstraint) {
501 ComponentInstanceProperty componentInstanceProperty = null;
502 final Optional<ComponentInstance> optionalComponentInstances = parentComponent.getComponentInstances().stream()
503 .filter(componentInstance -> componentInstanceId.equalsIgnoreCase(componentInstance.getUniqueId())).findFirst();
504 if (optionalComponentInstances.isPresent()) {
505 final Optional<List<CapabilityDefinition>> optionalCapabilityDefinitionList = optionalComponentInstances.get().getCapabilities().values()
506 .stream().filter(capabilityDefinitions -> capabilityDefinitions.stream()
507 .allMatch(capabilityDefinition -> capabilityDefinition.getProperties() != null)).collect(Collectors.toList()).stream().filter(
508 capabilityDefinitions -> capabilityDefinitions.stream().allMatch(
509 capabilityDefinition -> capabilityDefinition.getProperties().stream().anyMatch(
510 componentInstanceProperty1 -> filterConstraint.getPropertyName()
511 .equalsIgnoreCase(componentInstanceProperty1.getName())))).findFirst();
512 if (optionalCapabilityDefinitionList.isPresent() && !optionalCapabilityDefinitionList.get().isEmpty()) {
513 componentInstanceProperty =
514 getComponentInstanceProperty(optionalCapabilityDefinitionList.get().get(0), filterConstraint.getPropertyName()).orElse(null);
518 if (componentInstanceProperty == null) {
519 return Either.right(componentsUtils.getResponseFormat(ActionStatus.SELECTED_PROPERTY_NOT_PRESENT, filterConstraint.getPropertyName()));
521 if (filterConstraint.getOperator().isComparable() && !TYPES_WITH_SCHEMA.contains(componentInstanceProperty.getType())
522 && !COMPARABLE_TYPES.contains(componentInstanceProperty.getType())) {
523 return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_OPERATOR_PROVIDED, filterConstraint.getPropertyName(),
524 filterConstraint.getOperator().getType()));
526 return isValidValueCheck(componentInstanceProperty.getType(), componentInstanceProperty.getSchemaType(), parentComponent.getModel(),
527 filterConstraint.getValue(), filterConstraint.getPropertyName());
530 private Optional<ComponentInstanceProperty> getComponentInstanceProperty(CapabilityDefinition capabilityDefinition, final String propertyName) {
531 return capabilityDefinition.getProperties().stream().filter(property -> property.getName().equals(propertyName)).findAny();
534 private Either<Boolean, ResponseFormat> isValidValueCheck(final String type, final String schemaType, final String model,
535 final Object value, final String propertyName) {
536 final Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> allDataTypesEither =
537 applicationDataTypeCache.getAll(model);
538 if (allDataTypesEither.isRight()) {
539 LOGGER.error("Could not validate filter value. Could not load data types for model {}", model);
540 return Either.right(componentsUtils.getResponseFormat(ActionStatus.DATA_TYPES_NOT_LOADED, model));
542 final Map<String, DataTypeDefinition> modelDataTypesMap = allDataTypesEither.left().value();
543 final ToscaPropertyType toscaPropertyType = ToscaPropertyType.isValidType(type);
544 if (toscaPropertyType == null && !modelDataTypesMap.containsKey(type)) {
545 return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_PROPERTY_TYPE, type, propertyName));
547 final String valueAsJsonString;
549 valueAsJsonString = new Gson().toJson(value);
550 } catch (final Exception e) {
551 LOGGER.debug("Unsupported property filter value", e);
553 componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_VALUE_PROVIDED, type, propertyName, String.valueOf(value)));
555 if (toscaPropertyType != null) {
556 if (toscaPropertyType.getValidator().isValid(valueAsJsonString, schemaType, modelDataTypesMap)) {
557 return Either.left(true);
560 if (DataTypeValidatorConverter.getInstance().isValid(valueAsJsonString, modelDataTypesMap.get(type), modelDataTypesMap)) {
561 return Either.left(true);
565 return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_VALUE_PROVIDED, type, propertyName, valueAsJsonString));
568 public Either<Boolean, ResponseFormat> validateSubstitutionFilter(final Component component,
569 final List<FilterConstraintDto> filterConstraintList) {
570 if (CollectionUtils.isEmpty(filterConstraintList)) {
571 return Either.right(componentsUtils.getResponseFormat(ActionStatus.CONSTRAINT_FORMAT_INCORRECT));
573 for (final FilterConstraintDto filterConstraintDto : filterConstraintList) {
574 final Either<Boolean, ResponseFormat> validationEither = validateSubstitutionFilter(component, filterConstraintDto);
575 if (validationEither.isRight()) {
576 return validationEither;
579 return Either.left(true);
582 public Either<Boolean, ResponseFormat> validateSubstitutionFilter(final Component component, final FilterConstraintDto filterConstraint) {
583 validateFilterConstraint(filterConstraint);
584 switch (filterConstraint.getValueType()) {
586 return validateStaticSubstitutionFilter(component, filterConstraint);
590 return validateSubstitutionFilterGetFunctionConstraint(component, filterConstraint);
592 return Either.left(true);
596 private Either<Boolean, ResponseFormat> validateSubstitutionFilterGetFunctionConstraint(final Component component,
597 final FilterConstraintDto filterConstraint) {
598 final ToscaGetFunctionDataDefinition toscaGetFunction = filterConstraint.getAsToscaGetFunction().orElse(null);
599 if (toscaGetFunction == null) {
600 return Either.right(componentsUtils.getResponseFormat(ActionStatus.TOSCA_FUNCTION_EXPECTED_ERROR));
603 if (CollectionUtils.isEmpty(component.getProperties())) {
605 componentsUtils.getResponseFormat(ActionStatus.FILTER_PROPERTY_NOT_FOUND, TARGET, getPropertyType(toscaGetFunction),
606 filterConstraint.getPropertyName())
610 final Optional<? extends PropertyDefinition> targetComponentProperty = component.getProperties().stream()
611 .filter(property -> property.getName().equals(filterConstraint.getPropertyName())).findFirst();
612 if (targetComponentProperty.isEmpty()) {
614 componentsUtils.getResponseFormat(ActionStatus.FILTER_PROPERTY_NOT_FOUND, TARGET, getPropertyType(toscaGetFunction),
615 filterConstraint.getPropertyName())
619 final Optional<? extends ToscaPropertyData> sourceSelectedProperty = findPropertyFromGetFunction(component, toscaGetFunction);
620 if (sourceSelectedProperty.isEmpty()) {
621 return Either.right(componentsUtils.getResponseFormat(ActionStatus.FILTER_PROPERTY_NOT_FOUND, SOURCE, getPropertyType(toscaGetFunction),
622 String.join("->", toscaGetFunction.getPropertyPathFromSource())));
625 final ResponseFormat responseFormat =
626 validatePropertyData(sourceSelectedProperty.get(), targetComponentProperty.get(),
627 filterConstraint.getOperator().isLengthConstraint());
628 if (responseFormat != null) {
629 return Either.right(responseFormat);
631 return Either.left(true);
634 private String getPropertyType(final ToscaGetFunctionDataDefinition toscaGetFunction) {
635 switch (toscaGetFunction.getType()) {