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