re base code
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / validation / PropertyValidator.java
1 package org.openecomp.sdc.be.components.validation;
2
3 import fj.data.Either;
4 import org.apache.commons.lang3.tuple.ImmutablePair;
5 import org.openecomp.sdc.be.components.impl.ResourceBusinessLogic;
6 import org.openecomp.sdc.be.components.impl.utils.ExceptionUtils;
7 import org.openecomp.sdc.be.config.BeEcompErrorManager;
8 import org.openecomp.sdc.be.dao.api.ActionStatus;
9 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
10 import org.openecomp.sdc.be.impl.ComponentsUtils;
11 import org.openecomp.sdc.be.model.DataTypeDefinition;
12 import org.openecomp.sdc.be.model.PropertyDefinition;
13 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
14 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
15 import org.openecomp.sdc.be.model.operations.impl.PropertyOperation;
16 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
17 import org.openecomp.sdc.exception.ResponseFormat;
18 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory;
20 import org.springframework.stereotype.Component;
21
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Optional;
25
26 @Component
27 public class PropertyValidator {
28
29     private final PropertyOperation propertyOperation;
30     private final ComponentsUtils componentsUtils;
31     private final ApplicationDataTypeCache applicationDataTypeCache;
32     private final ExceptionUtils exceptionUtils;
33     private static final Logger log = LoggerFactory.getLogger(ResourceBusinessLogic.class);
34
35     public PropertyValidator(PropertyOperation propertyOperation, ComponentsUtils componentsUtils,
36                              ApplicationDataTypeCache applicationDataTypeCache, ExceptionUtils exceptionUtils) {
37         this.exceptionUtils = exceptionUtils;
38         this.propertyOperation = propertyOperation;
39         this.componentsUtils = componentsUtils;
40         this.applicationDataTypeCache = applicationDataTypeCache;
41     }
42
43     public void thinPropertiesValidator(List<PropertyDefinition> properties,
44                                         List<PropertyDefinition> dbAnnotationTypeDefinitionProperties,
45                                         Map<String, DataTypeDefinition> allDataTypes){
46         for (PropertyDefinition property : properties) {
47             PropertyDefinition annotationTypeSpecificProperty = isPropertyInsideAnnotationTypeProperties(
48                     dbAnnotationTypeDefinitionProperties, property);
49             if(annotationTypeSpecificProperty!=null){
50                 verifyPropertyIsOfDefinedType(property, annotationTypeSpecificProperty, allDataTypes);
51             }
52         }
53     }
54
55     private void verifyPropertyIsOfDefinedType(PropertyDefinition property,
56                                                PropertyDefinition typeSpecificProperty,
57                                                Map<String, DataTypeDefinition> allDataTypes) {
58             propertyOperation.validateAndUpdatePropertyValue(typeSpecificProperty.getType(),
59                     property.getValue(), typeSpecificProperty.getSchemaType(), allDataTypes)
60                     .left()
61                     .on( error ->
62                     exceptionUtils.rollBackAndThrow(
63                             ActionStatus.INVALID_PROPERTY_TYPE, property.getType(), property.getName())
64             );
65     }
66
67     private PropertyDefinition isPropertyInsideAnnotationTypeProperties(
68             List<PropertyDefinition> dbAnnotationTypeDefinitionProperties, PropertyDefinition property) {
69         Optional<PropertyDefinition> optionalResult = dbAnnotationTypeDefinitionProperties.stream()
70                 .filter(prop -> prop.getName()
71                         .equals(property.getName()))
72                 .findFirst();
73         if (optionalResult.isPresent()){
74             return optionalResult.get();
75         }
76         ResponseFormat responseFormat = componentsUtils.getResponseFormat(
77                 ActionStatus.PROPERTY_NOT_FOUND, property.getType(), property.getName());
78         exceptionUtils.rollBackAndThrow(responseFormat);
79         return null;
80     }
81
82     public Either<Boolean, ResponseFormat> iterateOverProperties(List<PropertyDefinition> properties){
83         Either<Boolean, ResponseFormat> eitherResult = Either.left(true);
84         String type = null;
85         String innerType = null;
86         for (PropertyDefinition property : properties) {
87             if (!propertyOperation.isPropertyTypeValid(property)) {
88                 log.info("Invalid type for property {}", property);
89                 ResponseFormat responseFormat = componentsUtils.getResponseFormat(
90                         ActionStatus.INVALID_PROPERTY_TYPE, property.getType(), property.getName());
91                 eitherResult = Either.right(responseFormat);
92                 break;
93             }
94
95             Either<Map<String, DataTypeDefinition>, TitanOperationStatus> allDataTypes = applicationDataTypeCache.getAll();
96             if (allDataTypes.isRight()) {
97                 TitanOperationStatus status = allDataTypes.right().value();
98                 BeEcompErrorManager.getInstance().logInternalFlowError("AddPropertyToGroup", "Failed to validate property. Status is " + status, BeEcompErrorManager.ErrorSeverity.ERROR);
99                 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(DaoStatusConverter.convertTitanStatusToStorageStatus(status))));
100             }
101
102             type = property.getType();
103
104             if (type.equals(ToscaPropertyType.LIST.getType()) || type.equals(ToscaPropertyType.MAP.getType())) {
105                 ResponseFormat responseFormat = validateMapOrListPropertyType(property, allDataTypes.left().value());
106                 if(responseFormat != null)
107                     break;
108             }
109
110             if (!propertyOperation.isPropertyDefaultValueValid(property, allDataTypes.left().value())) {
111                 log.info("Invalid default value for property {}", property);
112                 ResponseFormat responseFormat;
113                 if (type.equals(ToscaPropertyType.LIST.getType()) || type.equals(ToscaPropertyType.MAP.getType())) {
114                     responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_COMPLEX_DEFAULT_VALUE,
115                             property.getName(), type, innerType, property.getDefaultValue());
116                 } else {
117                     responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_DEFAULT_VALUE,
118                             property.getName(), type, property.getDefaultValue());
119                 }
120                 eitherResult = Either.right(responseFormat);
121                 break;
122
123             }
124         }
125         return eitherResult;
126     }
127
128     private ResponseFormat validateMapOrListPropertyType(PropertyDefinition property, Map<String, DataTypeDefinition> allDataTypes) {
129         ResponseFormat responseFormat = null;
130         ImmutablePair<String, Boolean> propertyInnerTypeValid = propertyOperation
131                 .isPropertyInnerTypeValid(property, allDataTypes);
132         String propertyInnerType = propertyInnerTypeValid.getLeft();
133         if (!propertyInnerTypeValid.getRight().booleanValue()) {
134             log.info("Invalid inner type for property {}", property);
135             responseFormat = componentsUtils.getResponseFormat(
136                     ActionStatus.INVALID_PROPERTY_INNER_TYPE, propertyInnerType, property.getName());
137         }
138         return responseFormat;
139     }
140
141 }