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.gson.Gson;
24 import fj.data.Either;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.List;
29 import java.util.Optional;
31 import java.util.stream.Collectors;
32 import org.apache.commons.collections4.CollectionUtils;
33 import org.apache.commons.lang3.StringUtils;
34 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
35 import org.openecomp.sdc.be.dao.api.ActionStatus;
36 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
37 import org.openecomp.sdc.be.datatypes.elements.ToscaGetFunctionDataDefinition;
38 import org.openecomp.sdc.be.datatypes.enums.ConstraintType;
39 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
40 import org.openecomp.sdc.be.datatypes.enums.PropertyFilterTargetType;
41 import org.openecomp.sdc.be.datatypes.enums.PropertySource;
42 import org.openecomp.sdc.be.impl.ComponentsUtils;
43 import org.openecomp.sdc.be.model.CapabilityDefinition;
44 import org.openecomp.sdc.be.model.Component;
45 import org.openecomp.sdc.be.model.ComponentInstance;
46 import org.openecomp.sdc.be.model.ComponentInstanceInput;
47 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
48 import org.openecomp.sdc.be.model.DataTypeDefinition;
49 import org.openecomp.sdc.be.model.InputDefinition;
50 import org.openecomp.sdc.be.model.PropertyDefinition;
51 import org.openecomp.sdc.be.model.ToscaPropertyData;
52 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
53 import org.openecomp.sdc.be.model.dto.FilterConstraintDto;
54 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
55 import org.openecomp.sdc.be.model.tosca.validators.DataTypeValidatorConverter;
56 import org.openecomp.sdc.be.model.validation.FilterConstraintValidator;
57 import org.openecomp.sdc.exception.ResponseFormat;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
60 import org.springframework.beans.factory.annotation.Autowired;
62 @org.springframework.stereotype.Component("NodeFilterValidator")
63 public class NodeFilterValidator {
65 private static final Logger LOGGER = LoggerFactory.getLogger(NodeFilterValidator.class);
66 private static final String SOURCE = "Source";
67 private static final String TARGET = "Target";
68 private static final String INPUT_NOT_FOUND_LOG = "Input '{}' not found in parent component '{}', unique id '{}'";
69 private static final Set<String> TYPES_WITH_SCHEMA = Set.of(ToscaPropertyType.MAP.getType(), ToscaPropertyType.LIST.getType());
70 private static final Set<String> COMPARABLE_TYPES = Set.of(
71 ToscaPropertyType.SCALAR_UNIT_SIZE.getType(),
72 ToscaPropertyType.SCALAR_UNIT_TIME.getType(),
73 ToscaPropertyType.SCALAR_UNIT_BITRATE.getType(),
74 ToscaPropertyType.SCALAR_UNIT_FREQUENCY.getType(),
75 ToscaPropertyType.BOOLEAN.getType(),
76 ToscaPropertyType.STRING.getType(),
77 ToscaPropertyType.INTEGER.getType(),
78 ToscaPropertyType.FLOAT.getType());
79 private final ComponentsUtils componentsUtils;
80 private final ApplicationDataTypeCache applicationDataTypeCache;
81 private final FilterConstraintValidator filterConstraintValidator;
84 public NodeFilterValidator(final ComponentsUtils componentsUtils, final ApplicationDataTypeCache applicationDataTypeCache,
85 final FilterConstraintValidator filterConstraintValidator) {
86 this.componentsUtils = componentsUtils;
87 this.applicationDataTypeCache = applicationDataTypeCache;
88 this.filterConstraintValidator = filterConstraintValidator;
91 private static List<? extends ToscaPropertyData> getSelfPropertyFromGetFunction(final Component component,
92 final ToscaGetFunctionDataDefinition toscaGetFunction) {
93 switch (toscaGetFunction.getFunctionType()) {
95 if (component.getInputs() != null) {
96 return component.getInputs();
100 if (component.getProperties() != null) {
101 return component.getProperties();
105 if (component.getAttributes() != null) {
106 return component.getAttributes();
113 public Either<Boolean, ResponseFormat> validateComponentInstanceExist(final Component component, final String componentInstanceId) {
114 if (component == null || StringUtils.isEmpty(componentInstanceId)) {
115 LOGGER.error("Expecting a component and a component instance id, given was '{}' and '{}'", component, componentInstanceId);
116 final String componentName = component == null ? "?" : component.getName();
117 return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND, componentName, componentInstanceId));
119 if (CollectionUtils.isEmpty(component.getComponentInstances()) || component.getComponentInstances().stream()
120 .noneMatch(ci -> ci.getUniqueId().equals(componentInstanceId))) {
121 LOGGER.error("Component '{}' node instance list is empty or component instance '{}' not found",
122 component.getUniqueId(), componentInstanceId);
123 return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND,
124 component.getName(), componentInstanceId));
126 return Either.left(Boolean.TRUE);
129 public Either<Boolean, ResponseFormat> validateFilter(final Component parentComponent, final String componentInstanceId,
130 final List<FilterConstraintDto> filterConstraint) {
131 if (CollectionUtils.isEmpty(filterConstraint)) {
132 return Either.left(true);
134 for (final FilterConstraintDto filterConstraintDto : filterConstraint) {
135 final Either<Boolean, ResponseFormat> validationEither =
136 validateFilter(parentComponent, componentInstanceId, filterConstraintDto);
137 if (validationEither.isRight()) {
138 return validationEither;
141 return Either.left(true);
144 public Either<Boolean, ResponseFormat> validateFilter(final Component parentComponent, final String componentInstanceId,
145 final FilterConstraintDto filterConstraint) {
146 validateFilterConstraint(filterConstraint);
147 switch (filterConstraint.getValueType()) {
149 if (filterConstraint.isCapabilityPropertyFilter()) {
150 return validateStaticValueAndOperatorOfCapabilityProperties(parentComponent, componentInstanceId, filterConstraint);
152 return validateStaticValueAndOperator(parentComponent, componentInstanceId, filterConstraint);
155 return validatePropertyConstraint(parentComponent, componentInstanceId, filterConstraint, filterConstraint.getCapabilityName());
157 return validateInputConstraint(parentComponent, componentInstanceId, filterConstraint);
159 return Either.left(true);
163 private void validateFilterConstraint(final FilterConstraintDto filterConstraint) {
164 filterConstraintValidator.validate(filterConstraint);
167 private Either<Boolean, ResponseFormat> validatePropertyConstraint(final Component parentComponent, final String componentInstanceId,
168 final FilterConstraintDto filterConstraint, final String capabilityName) {
169 String source = SOURCE;
170 ResponseFormat responseFormat = null;
171 List<ToscaGetFunctionDataDefinition> toscaGetFunctionDataDefinitionList = new ArrayList<>();
172 final ToscaGetFunctionDataDefinition toscaGetFunction = filterConstraint.getAsToscaGetFunction().orElse(null);
173 if (toscaGetFunction == null || !(filterConstraint.getValue() instanceof ToscaGetFunctionDataDefinition)) {
174 final List<ToscaGetFunctionDataDefinition> toscaGetFunctionList = filterConstraint.getAsListToscaGetFunction().orElse(null);
175 if (toscaGetFunctionList == null || toscaGetFunctionList.isEmpty() || !(filterConstraint.getValue() instanceof List)) {
176 return Either.right(componentsUtils.getResponseFormat(ActionStatus.TOSCA_FUNCTION_EXPECTED_ERROR));
178 toscaGetFunctionDataDefinitionList = toscaGetFunctionList;
181 toscaGetFunctionDataDefinitionList.add(toscaGetFunction);
183 Boolean allGood = true;
184 for (ToscaGetFunctionDataDefinition _toscaGetFunction : toscaGetFunctionDataDefinitionList) {
186 final Optional<? extends ToscaPropertyData> sourceSelectedProperty =
187 findPropertyFromGetFunction(parentComponent, _toscaGetFunction);
188 if (sourceSelectedProperty.isPresent()) {
189 Optional<? extends PropertyDefinition> targetComponentInstanceProperty =
190 getInstanceProperties(parentComponent, componentInstanceId, capabilityName, filterConstraint);
192 source = targetComponentInstanceProperty.isEmpty() ? TARGET : SOURCE;
193 if (targetComponentInstanceProperty.isPresent()) {
195 validatePropertyData(sourceSelectedProperty.get(), targetComponentInstanceProperty.get(),
196 filterConstraint.getOperator().isLengthConstraint());
197 if (responseFormat != null) {
204 final String missingProperty =
205 SOURCE.equals(source) ? filterConstraint.getValue().toString() : filterConstraint.getPropertyName();
207 componentsUtils.getResponseFormat(ActionStatus.FILTER_PROPERTY_NOT_FOUND, source, missingProperty);
212 final String missingProperty =
213 SOURCE.equals(source) ? filterConstraint.getValue().toString() : filterConstraint.getPropertyName();
215 componentsUtils.getResponseFormat(ActionStatus.FILTER_PROPERTY_NOT_FOUND, source, missingProperty);
220 return Either.left(true);
222 return Either.right(responseFormat);
225 private Optional<? extends ToscaPropertyData> findPropertyFromGetFunction(final Component parentComponent,
226 final ToscaGetFunctionDataDefinition toscaGetFunction) {
227 List<? extends ToscaPropertyData> sourcePropertyDefinitions;
228 if (PropertySource.SELF == toscaGetFunction.getPropertySource()) {
229 sourcePropertyDefinitions = getSelfPropertyFromGetFunction(parentComponent, toscaGetFunction);
231 sourcePropertyDefinitions = getInstancePropertiesBasedOnGetFunctionSource(parentComponent, toscaGetFunction);
233 final List<String> propertyPath = toscaGetFunction.getPropertyPathFromSource();
234 final Optional<? extends ToscaPropertyData> sourceProperty = sourcePropertyDefinitions.stream()
235 .filter(propertyDefinition -> propertyDefinition.getName().equals(propertyPath.get(0))).findFirst();
236 if (sourceProperty.isEmpty() || propertyPath.size() == 1) {
237 return sourceProperty;
239 final Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> allDataTypesEither =
240 applicationDataTypeCache.getAll(parentComponent.getModel());
241 if (allDataTypesEither.isRight()) {
242 return Optional.empty();
244 return findSubProperty(propertyPath.subList(1, propertyPath.size()), sourceProperty.get().getType(), allDataTypesEither.left().value());
247 private List<? extends ToscaPropertyData> getInstancePropertiesBasedOnGetFunctionSource(final Component parentComponent,
248 final ToscaGetFunctionDataDefinition toscaGetFunction) {
249 final ComponentInstance componentInstance = parentComponent.getComponentInstances().stream()
250 .filter(componentInstance1 -> componentInstance1.getName().equals(toscaGetFunction.getSourceName()))
253 if (componentInstance == null) {
256 final List<? extends ToscaPropertyData> instanceProperties;
257 switch (toscaGetFunction.getFunctionType()) {
259 instanceProperties = parentComponent.getComponentInstancesProperties().get(componentInstance.getUniqueId());
262 instanceProperties = parentComponent.getComponentInstancesAttributes().get(componentInstance.getUniqueId());
265 instanceProperties = List.of();
267 if (instanceProperties == null) {
270 return instanceProperties;
273 private Optional<PropertyDefinition> findSubProperty(final List<String> propertyPath, final String parentPropertyType,
274 final Map<String, DataTypeDefinition> modelDataTypes) {
275 final DataTypeDefinition dataTypeDefinition = modelDataTypes.get(parentPropertyType);
276 if (CollectionUtils.isEmpty(dataTypeDefinition.getProperties())) {
277 return Optional.empty();
279 final PropertyDefinition propertyDefinition = dataTypeDefinition.getProperties().stream()
280 .filter(propertyDefinition1 -> propertyDefinition1.getName().equals(propertyPath.get(0))).findFirst().orElse(null);
281 if (propertyDefinition == null) {
282 return Optional.empty();
284 if (propertyPath.size() == 1) {
285 return Optional.of(propertyDefinition);
287 return findSubProperty(propertyPath.subList(1, propertyPath.size()), propertyDefinition.getType(), modelDataTypes);
290 private Optional<? extends PropertyDefinition> getInstanceProperties(final Component parentComponent, final String componentInstanceId,
291 final String capabilityName, final FilterConstraintDto filterConstraint) {
292 if (StringUtils.isEmpty(capabilityName)) {
293 OriginTypeEnum componentInstanceType = getComponentInstanceOriginType(parentComponent, componentInstanceId);
294 if (componentInstanceType == null) {
295 return Optional.empty();
297 PropertyDefinition componentInstanceProperty =
298 getComponentInstanceProperty(componentInstanceType, parentComponent, componentInstanceId, filterConstraint);
299 if (componentInstanceProperty == null) {
300 throw new ByActionStatusComponentException(ActionStatus.SELECTED_PROPERTY_NOT_PRESENT, filterConstraint.getPropertyName());
302 if (componentInstanceProperty instanceof ComponentInstanceInput) {
303 return parentComponent.getComponentInstancesInputs().get(componentInstanceId).stream()
304 .filter(property -> filterConstraint.getPropertyName().equals(property.getName())).findFirst();
306 return parentComponent.getComponentInstancesProperties().get(componentInstanceId).stream()
307 .filter(property -> filterConstraint.getPropertyName().equals(property.getName())).findFirst();
309 final Optional<ComponentInstance> componentInstanceOptional = parentComponent.getComponentInstances().stream()
310 .filter(componentInstance -> componentInstance.getUniqueId().equals(componentInstanceId)).findAny();
311 if (componentInstanceOptional.isPresent()) {
312 for (final List<CapabilityDefinition> listOfCaps : componentInstanceOptional.get().getCapabilities().values()) {
313 final Optional<CapabilityDefinition> capDef = listOfCaps.stream().filter(cap -> cap.getName().equals(capabilityName)).findAny();
314 if (capDef.isPresent()) {
315 return capDef.get().getProperties().stream().filter(property -> filterConstraint.getPropertyName().equals(property.getName()))
321 return Optional.empty();
324 private Either<Boolean, ResponseFormat> validateInputConstraint(final Component parentComponent, final String componentInstanceId,
325 final FilterConstraintDto filterConstraint) {
326 final List<InputDefinition> sourceInputDefinition = parentComponent.getInputs();
327 if (CollectionUtils.isEmpty(sourceInputDefinition)) {
328 LOGGER.debug("Parent component '{}', unique id '{}', does not have inputs", parentComponent.getName(), parentComponent.getUniqueId());
329 return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_DOES_NOT_HAVE_INPUTS, parentComponent.getName()));
331 if (!(filterConstraint.getValue() instanceof ToscaGetFunctionDataDefinition)) {
332 if (filterConstraint.getValue() instanceof List) {
333 Optional optValid = ((List<?>) filterConstraint.getValue()).stream().filter(filterConstraintValue ->
334 !(filterConstraintValue instanceof ToscaGetFunctionDataDefinition)).findAny();
335 if (optValid.isPresent()) {
336 return Either.right(componentsUtils.getResponseFormat(ActionStatus.TOSCA_FUNCTION_EXPECTED_ERROR));
339 return Either.right(componentsUtils.getResponseFormat(ActionStatus.TOSCA_FUNCTION_EXPECTED_ERROR));
342 if (filterConstraint.getValue() instanceof ToscaGetFunctionDataDefinition) {
343 final ToscaGetFunctionDataDefinition getFunction =
344 (ToscaGetFunctionDataDefinition) filterConstraint.getValue();
345 final List<String> propertyPathFromSource = getFunction.getPropertyPathFromSource();
346 Optional<? extends PropertyDefinition> sourceSelectedProperty =
347 sourceInputDefinition.stream().filter(input -> input.getName().equals(propertyPathFromSource.get(0)))
349 if (sourceSelectedProperty.isEmpty()) {
350 LOGGER.debug(INPUT_NOT_FOUND_LOG,
351 propertyPathFromSource.get(0), parentComponent.getName(), parentComponent.getUniqueId());
353 componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INPUT_NOT_FOUND,
354 propertyPathFromSource.get(0), parentComponent.getName())
357 if (propertyPathFromSource.size() > 1) {
358 final Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> allDataTypesEither =
359 applicationDataTypeCache.getAll(parentComponent.getModel());
360 if (allDataTypesEither.isRight()) {
361 LOGGER.error("Could not load data types for model {}", parentComponent.getModel());
362 return Either.right(componentsUtils.getResponseFormat(ActionStatus.DATA_TYPES_NOT_LOADED,
363 parentComponent.getModel()));
365 sourceSelectedProperty =
366 findSubProperty(propertyPathFromSource.subList(1, propertyPathFromSource.size()),
367 sourceSelectedProperty.get().getType(),
368 allDataTypesEither.left().value());
370 final Optional<? extends PropertyDefinition> targetComponentInstanceProperty;
371 if (PropertyFilterTargetType.CAPABILITY.equals(filterConstraint.getTargetType())) {
372 final CapabilityDefinition capability = parentComponent.getComponentInstances().stream()
373 .filter(componentInstance -> componentInstance.getUniqueId().equals(componentInstanceId))
374 .map(componentInstance -> componentInstance.getCapabilities().values())
375 .flatMap(Collection::stream)
376 .flatMap(Collection::stream)
377 .filter(capabilityDefinition -> capabilityDefinition.getName()
378 .equals(filterConstraint.getCapabilityName()))
379 .findFirst().orElse(null);
380 if (capability == null) {
382 componentsUtils.getResponseFormat(ActionStatus.CAPABILITY_NOT_FOUND_IN_COMPONENT,
383 filterConstraint.getCapabilityName(), parentComponent.getComponentType().getValue(),
384 parentComponent.getName())
387 targetComponentInstanceProperty = capability.getProperties().stream()
388 .filter(property -> filterConstraint.getPropertyName().equals(property.getName()))
391 targetComponentInstanceProperty =
392 parentComponent.getComponentInstancesProperties()
393 .get(componentInstanceId).stream()
394 .filter(property -> filterConstraint.getPropertyName().equals(property.getName()))
397 if (sourceSelectedProperty.isPresent() && targetComponentInstanceProperty.isPresent()) {
398 final ResponseFormat responseFormat =
399 validatePropertyData(sourceSelectedProperty.get(), targetComponentInstanceProperty.get(),
400 filterConstraint.getOperator().isLengthConstraint());
401 if (responseFormat != null) {
402 return Either.right(responseFormat);
404 return Either.left(true);
407 return Either.right(componentsUtils.getResponseFormat(ActionStatus.INPUTS_NOT_FOUND));
409 return Either.left(true);
412 private <T extends ToscaPropertyData> ResponseFormat validatePropertyData(final T sourcePropDefinition,
413 final T targetPropDefinition,
414 final boolean isLengthConstraint) {
415 final String sourceType = sourcePropDefinition.getType();
416 final String targetType = targetPropDefinition.getType();
417 if (!isLengthConstraint) {
418 if (sourceType.equals(targetType)) {
419 if (TYPES_WITH_SCHEMA.contains(sourceType)) {
420 final String sourceSchemaType = sourcePropDefinition.getSchemaType();
421 final String targetSchemaType = targetPropDefinition.getSchemaType();
422 if (sourceSchemaType != null && !sourceSchemaType.equals(targetSchemaType)) {
423 return componentsUtils.getResponseFormat(ActionStatus.SOURCE_TARGET_SCHEMA_MISMATCH,
424 targetPropDefinition.getName(), targetSchemaType, sourcePropDefinition.getName(),
430 if (null != ((PropertyDefinition) sourcePropDefinition).getSchemaProperty()) {
431 if (((PropertyDefinition) sourcePropDefinition).getSchemaProperty().getType().equals(targetType)) {
432 if (TYPES_WITH_SCHEMA.contains(((PropertyDefinition) sourcePropDefinition).getSchemaProperty().getType())) {
433 final String sourceSchemaType = sourcePropDefinition.getSchemaType();
434 final String targetSchemaType = targetPropDefinition.getSchemaType();
435 if (sourceSchemaType != null && !sourceSchemaType.equals(targetSchemaType)) {
436 return componentsUtils.getResponseFormat(ActionStatus.SOURCE_TARGET_SCHEMA_MISMATCH,
437 targetPropDefinition.getName(), targetSchemaType, sourcePropDefinition.getName(),
446 if (sourceType.equalsIgnoreCase("integer")) {
447 if (TYPES_WITH_SCHEMA.contains(sourceType)) {
448 final String sourceSchemaType = sourcePropDefinition.getSchemaType();
449 if (sourceSchemaType != null && !sourceSchemaType.equalsIgnoreCase("integer")) {
450 return componentsUtils.getResponseFormat(ActionStatus.SOURCE_TARGET_SCHEMA_MISMATCH,
451 targetPropDefinition.getName(), "integer", sourcePropDefinition.getName(),
458 return componentsUtils.getResponseFormat(ActionStatus.SOURCE_TARGET_PROPERTY_TYPE_MISMATCH,
459 sourcePropDefinition.getName(), sourcePropDefinition.getType(), targetPropDefinition.getName(), targetPropDefinition.getType());
462 private Either<Boolean, ResponseFormat> validateStaticValueAndOperator(final Component parentComponent, final String componentInstanceId,
463 final FilterConstraintDto filterConstraint) {
464 OriginTypeEnum componentInstanceType = getComponentInstanceOriginType(parentComponent, componentInstanceId);
465 if (componentInstanceType == null) {
466 return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND, componentInstanceId));
468 PropertyDefinition componentInstanceProperty =
469 getComponentInstanceProperty(componentInstanceType, parentComponent, componentInstanceId, filterConstraint);
470 if (componentInstanceProperty == null) {
471 return Either.right(componentsUtils.getResponseFormat(ActionStatus.SELECTED_PROPERTY_NOT_PRESENT, filterConstraint.getPropertyName()));
473 if (filterConstraint.getOperator().isComparable() && !TYPES_WITH_SCHEMA.contains(componentInstanceProperty.getType())
474 && !COMPARABLE_TYPES.contains(componentInstanceProperty.getType())) {
475 return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_OPERATOR_PROVIDED, filterConstraint.getPropertyName(),
476 filterConstraint.getOperator().getType()));
478 if (filterConstraint.getOperator().equals(ConstraintType.VALID_VALUES) || filterConstraint.getOperator().equals(ConstraintType.IN_RANGE)) {
479 return isValidValueCheck("list", componentInstanceProperty.getType(), parentComponent.getModel(),
480 filterConstraint.getValue(), filterConstraint.getPropertyName());
482 if (filterConstraint.getOperator().isLengthConstraint() && componentInstanceProperty.getType().equals("list")) {
483 return Either.left(true);
485 return isValidValueCheck(componentInstanceProperty.getType(), componentInstanceProperty.getSchemaType(), parentComponent.getModel(),
486 filterConstraint.getValue(), filterConstraint.getPropertyName());
489 private PropertyDefinition getComponentInstanceProperty(OriginTypeEnum componentInstanceType, Component parentComponent,
490 String componentInstanceId, FilterConstraintDto filterConstraint) {
491 if (isInput(componentInstanceType)) {
492 return parentComponent.getComponentInstancesInputs()
493 .get(componentInstanceId).stream().filter(input -> filterConstraint.getPropertyName().equals(input.getName()))
497 return parentComponent.getComponentInstancesProperties()
498 .get(componentInstanceId).stream().filter(property -> filterConstraint.getPropertyName().equals(property.getName()))
503 private OriginTypeEnum getComponentInstanceOriginType(Component parentComponent, String componentInstanceId) {
504 Optional<ComponentInstance> componentInstanceOptional = parentComponent.getComponentInstanceById(componentInstanceId);
505 if (componentInstanceOptional.isPresent()) {
506 ComponentInstance componentInstance = componentInstanceOptional.get();
507 return componentInstance.getOriginType();
512 private boolean isInput(OriginTypeEnum instanceType) {
513 return OriginTypeEnum.VF.equals(instanceType) || OriginTypeEnum.PNF.equals(instanceType) || OriginTypeEnum.CVFC.equals(instanceType) ||
514 OriginTypeEnum.CR.equals(instanceType);
517 private Either<Boolean, ResponseFormat> validateStaticSubstitutionFilter(final Component component,
518 final FilterConstraintDto filterConstraint) {
520 final PropertyDefinition componentProperty = component.getProperties().stream()
521 .filter(property -> property.getName().equals(filterConstraint.getPropertyName())).findFirst().orElse(null);
522 if (componentProperty == null) {
523 return Either.right(componentsUtils.getResponseFormat(ActionStatus.SELECTED_PROPERTY_NOT_PRESENT, filterConstraint.getPropertyName()));
525 if (filterConstraint.getOperator().isComparable() && !TYPES_WITH_SCHEMA.contains(componentProperty.getType())
526 && !COMPARABLE_TYPES.contains(componentProperty.getType())) {
527 return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_OPERATOR_PROVIDED, filterConstraint.getPropertyName(),
528 filterConstraint.getOperator().getType()));
530 if (filterConstraint.getOperator().equals(ConstraintType.VALID_VALUES) || filterConstraint.getOperator().equals(ConstraintType.IN_RANGE)) {
531 return isValidValueCheck("list", componentProperty.getType(), component.getModel(),
532 filterConstraint.getValue(), filterConstraint.getPropertyName());
534 return isValidValueCheck(componentProperty.getType(), componentProperty.getSchemaType(), component.getModel(),
535 filterConstraint.getValue(), filterConstraint.getPropertyName());
538 private Either<Boolean, ResponseFormat> validateStaticValueAndOperatorOfCapabilityProperties(final Component parentComponent,
539 final String componentInstanceId,
540 final FilterConstraintDto filterConstraint) {
541 ComponentInstanceProperty componentInstanceProperty = null;
542 final Optional<ComponentInstance> optionalComponentInstances = parentComponent.getComponentInstances().stream()
543 .filter(componentInstance -> componentInstanceId.equalsIgnoreCase(componentInstance.getUniqueId())).findFirst();
544 if (optionalComponentInstances.isPresent()) {
545 final Optional<List<CapabilityDefinition>> optionalCapabilityDefinitionList = optionalComponentInstances.get().getCapabilities().values()
546 .stream().filter(capabilityDefinitions -> capabilityDefinitions.stream()
547 .allMatch(capabilityDefinition -> capabilityDefinition.getProperties() != null)).collect(Collectors.toList()).stream().filter(
548 capabilityDefinitions -> capabilityDefinitions.stream().allMatch(
549 capabilityDefinition -> capabilityDefinition.getProperties().stream().anyMatch(
550 componentInstanceProperty1 -> filterConstraint.getPropertyName()
551 .equalsIgnoreCase(componentInstanceProperty1.getName())))).findFirst();
552 if (optionalCapabilityDefinitionList.isPresent() && !optionalCapabilityDefinitionList.get().isEmpty()) {
553 componentInstanceProperty =
554 getComponentInstanceProperty(optionalCapabilityDefinitionList.get().get(0), filterConstraint.getPropertyName()).orElse(null);
558 if (componentInstanceProperty == null) {
559 return Either.right(componentsUtils.getResponseFormat(ActionStatus.SELECTED_PROPERTY_NOT_PRESENT, filterConstraint.getPropertyName()));
561 if (filterConstraint.getOperator().isComparable() && !TYPES_WITH_SCHEMA.contains(componentInstanceProperty.getType())
562 && !COMPARABLE_TYPES.contains(componentInstanceProperty.getType())) {
563 return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_OPERATOR_PROVIDED, filterConstraint.getPropertyName(),
564 filterConstraint.getOperator().getType()));
566 return isValidValueCheck(componentInstanceProperty.getType(), componentInstanceProperty.getSchemaType(), parentComponent.getModel(),
567 filterConstraint.getValue(), filterConstraint.getPropertyName());
570 private Optional<ComponentInstanceProperty> getComponentInstanceProperty(CapabilityDefinition capabilityDefinition, final String propertyName) {
571 return capabilityDefinition.getProperties().stream().filter(property -> property.getName().equals(propertyName)).findAny();
574 private Either<Boolean, ResponseFormat> isValidValueCheck(final String type, final String schemaType, final String model,
575 final Object value, final String propertyName) {
576 final Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> allDataTypesEither =
577 applicationDataTypeCache.getAll(model);
578 if (allDataTypesEither.isRight()) {
579 LOGGER.error("Could not validate filter value. Could not load data types for model {}", model);
580 return Either.right(componentsUtils.getResponseFormat(ActionStatus.DATA_TYPES_NOT_LOADED, model));
582 final Map<String, DataTypeDefinition> modelDataTypesMap = allDataTypesEither.left().value();
583 final ToscaPropertyType toscaPropertyType = ToscaPropertyType.isValidType(type);
584 if (toscaPropertyType == null && !modelDataTypesMap.containsKey(type)) {
585 return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_PROPERTY_TYPE, type, propertyName));
587 final String valueAsJsonString;
589 valueAsJsonString = new Gson().toJson(value);
590 } catch (final Exception e) {
591 LOGGER.debug("Unsupported property filter value", e);
593 componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_VALUE_PROVIDED, type, propertyName, String.valueOf(value)));
595 if (toscaPropertyType != null) {
596 if (toscaPropertyType.getValidator().isValid(valueAsJsonString, schemaType, modelDataTypesMap)) {
597 return Either.left(true);
600 if (DataTypeValidatorConverter.getInstance().isValid(valueAsJsonString, modelDataTypesMap.get(type), modelDataTypesMap)) {
601 return Either.left(true);
605 return Either.right(componentsUtils.getResponseFormat(ActionStatus.UNSUPPORTED_VALUE_PROVIDED, type, propertyName, valueAsJsonString));
608 public Either<Boolean, ResponseFormat> validateSubstitutionFilter(final Component component,
609 final List<FilterConstraintDto> filterConstraintList) {
610 if (CollectionUtils.isEmpty(filterConstraintList)) {
611 return Either.right(componentsUtils.getResponseFormat(ActionStatus.CONSTRAINT_FORMAT_INCORRECT));
613 for (final FilterConstraintDto filterConstraintDto : filterConstraintList) {
614 final Either<Boolean, ResponseFormat> validationEither = validateSubstitutionFilter(component, filterConstraintDto);
615 if (validationEither.isRight()) {
616 return validationEither;
619 return Either.left(true);
622 public Either<Boolean, ResponseFormat> validateSubstitutionFilter(final Component component, final FilterConstraintDto filterConstraint) {
623 validateFilterConstraint(filterConstraint);
624 switch (filterConstraint.getValueType()) {
626 return validateStaticSubstitutionFilter(component, filterConstraint);
630 return validateSubstitutionFilterGetFunctionConstraint(component, filterConstraint);
632 return Either.left(true);
636 private Either<Boolean, ResponseFormat> validateSubstitutionFilterGetFunctionConstraint(final Component component,
637 final FilterConstraintDto filterConstraint) {
638 final ToscaGetFunctionDataDefinition toscaGetFunction = filterConstraint.getAsToscaGetFunction().orElse(null);
639 if (toscaGetFunction == null) {
640 return Either.right(componentsUtils.getResponseFormat(ActionStatus.TOSCA_FUNCTION_EXPECTED_ERROR));
643 if (CollectionUtils.isEmpty(component.getProperties())) {
645 componentsUtils.getResponseFormat(ActionStatus.FILTER_PROPERTY_NOT_FOUND, TARGET, getPropertyType(toscaGetFunction),
646 filterConstraint.getPropertyName())
650 final Optional<? extends PropertyDefinition> targetComponentProperty = component.getProperties().stream()
651 .filter(property -> property.getName().equals(filterConstraint.getPropertyName())).findFirst();
652 if (targetComponentProperty.isEmpty()) {
654 componentsUtils.getResponseFormat(ActionStatus.FILTER_PROPERTY_NOT_FOUND, TARGET, getPropertyType(toscaGetFunction),
655 filterConstraint.getPropertyName())
659 final Optional<? extends ToscaPropertyData> sourceSelectedProperty = findPropertyFromGetFunction(component, toscaGetFunction);
660 if (sourceSelectedProperty.isEmpty()) {
661 return Either.right(componentsUtils.getResponseFormat(ActionStatus.FILTER_PROPERTY_NOT_FOUND, SOURCE, getPropertyType(toscaGetFunction),
662 String.join("->", toscaGetFunction.getPropertyPathFromSource())));
665 final ResponseFormat responseFormat =
666 validatePropertyData(sourceSelectedProperty.get(), targetComponentProperty.get(),
667 filterConstraint.getOperator().isLengthConstraint());
668 if (responseFormat != null) {
669 return Either.right(responseFormat);
671 return Either.left(true);
674 private String getPropertyType(final ToscaGetFunctionDataDefinition toscaGetFunction) {
675 switch (toscaGetFunction.getType()) {