ed37347a45d280ab395836b0cb4b8cee407fddfb
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / validation / ToscaFunctionValidatorImpl.java
1 /*
2  * -
3  *  ============LICENSE_START=======================================================
4  *  Copyright (C) 2022 Nordix Foundation.
5  *  ================================================================================
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *       http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  *
18  *  SPDX-License-Identifier: Apache-2.0
19  *  ============LICENSE_END=========================================================
20  */
21
22 package org.openecomp.sdc.be.components.impl.validation;
23
24 import fj.data.Either;
25 import java.util.List;
26 import java.util.Map;
27 import org.apache.commons.collections.CollectionUtils;
28 import org.apache.commons.lang3.StringUtils;
29 import org.onap.sdc.tosca.datatypes.model.PropertyType;
30 import org.openecomp.sdc.be.components.impl.exceptions.ToscaFunctionExceptionSupplier;
31 import org.openecomp.sdc.be.components.impl.exceptions.ToscaGetFunctionExceptionSupplier;
32 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
33 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
34 import org.openecomp.sdc.be.datatypes.elements.ToscaGetFunctionDataDefinition;
35 import org.openecomp.sdc.be.datatypes.enums.PropertySource;
36 import org.openecomp.sdc.be.datatypes.tosca.ToscaGetFunctionType;
37 import org.openecomp.sdc.be.model.Component;
38 import org.openecomp.sdc.be.model.ComponentInstance;
39 import org.openecomp.sdc.be.model.DataTypeDefinition;
40 import org.openecomp.sdc.be.model.ToscaPropertyData;
41 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
42 import org.openecomp.sdc.be.model.validation.ToscaFunctionValidator;
43
44 @org.springframework.stereotype.Component
45 public class ToscaFunctionValidatorImpl implements ToscaFunctionValidator {
46
47     private final ApplicationDataTypeCache applicationDataTypeCache;
48
49     public ToscaFunctionValidatorImpl(final ApplicationDataTypeCache applicationDataTypeCache) {
50         this.applicationDataTypeCache = applicationDataTypeCache;
51     }
52
53     @Override
54     public <T extends PropertyDataDefinition> void validate(T property, final Component containerComponent) {
55         if (property.getToscaFunction().getType() == null) {
56             throw ToscaFunctionExceptionSupplier.missingFunctionType().get();
57         }
58         if (property.isToscaGetFunction()) {
59             validateToscaGetFunction(property, containerComponent);
60         }
61     }
62
63     private <T extends PropertyDataDefinition> void validateToscaGetFunction(T property, Component parentComponent) {
64         final ToscaGetFunctionDataDefinition toscaGetFunction = (ToscaGetFunctionDataDefinition) property.getToscaFunction();
65         validateGetToscaFunctionAttributes(toscaGetFunction);
66         validateGetPropertySource(toscaGetFunction.getFunctionType(), toscaGetFunction.getPropertySource());
67         if (toscaGetFunction.getFunctionType() == ToscaGetFunctionType.GET_INPUT) {
68             validateGetFunction(property, parentComponent.getInputs(), parentComponent.getModel());
69             return;
70         }
71         if (toscaGetFunction.getFunctionType() == ToscaGetFunctionType.GET_PROPERTY) {
72             if (toscaGetFunction.getPropertySource() == PropertySource.SELF) {
73                 validateGetFunction(property, parentComponent.getProperties(), parentComponent.getModel());
74             } else if (toscaGetFunction.getPropertySource() == PropertySource.INSTANCE) {
75                 final ComponentInstance componentInstance =
76                     parentComponent.getComponentInstanceById(toscaGetFunction.getSourceUniqueId())
77                         .orElseThrow(ToscaGetFunctionExceptionSupplier.instanceNotFound(toscaGetFunction.getSourceName()));
78                 validateGetFunction(property, componentInstance.getProperties(), parentComponent.getModel());
79             }
80
81             return;
82         }
83         if (toscaGetFunction.getFunctionType() == ToscaGetFunctionType.GET_ATTRIBUTE) {
84             if (toscaGetFunction.getPropertySource() == PropertySource.SELF) {
85                 validateGetFunction(property, parentComponent.getAttributes(), parentComponent.getModel());
86             } else if (toscaGetFunction.getPropertySource() == PropertySource.INSTANCE) {
87                 final ComponentInstance componentInstance =
88                     parentComponent.getComponentInstanceById(toscaGetFunction.getSourceUniqueId())
89                         .orElseThrow(ToscaGetFunctionExceptionSupplier.instanceNotFound(toscaGetFunction.getSourceName()));
90                 validateGetFunction(property, componentInstance.getAttributes(), parentComponent.getModel());
91             }
92
93             return;
94         }
95
96         throw ToscaGetFunctionExceptionSupplier.functionNotSupported(toscaGetFunction.getFunctionType()).get();
97     }
98
99     private <T extends PropertyDataDefinition> void validateGetFunction(final T property,
100                                                                     final List<? extends ToscaPropertyData> parentProperties,
101                                                                     final String model) {
102         final ToscaGetFunctionDataDefinition toscaGetFunction = (ToscaGetFunctionDataDefinition) property.getToscaFunction();
103         if (CollectionUtils.isEmpty(parentProperties)) {
104             throw ToscaGetFunctionExceptionSupplier
105                 .propertyNotFoundOnTarget(toscaGetFunction.getPropertyName(), toscaGetFunction.getPropertySource(),
106                     toscaGetFunction.getFunctionType()
107                 ).get();
108         }
109         final String getFunctionPropertyUniqueId = toscaGetFunction.getPropertyUniqueId();
110         ToscaPropertyData referredProperty = parentProperties.stream()
111             .filter(property1 -> getFunctionPropertyUniqueId.equals(property1.getUniqueId()))
112             .findFirst()
113             .orElseThrow(ToscaGetFunctionExceptionSupplier
114                 .propertyNotFoundOnTarget(toscaGetFunction.getPropertyName(), toscaGetFunction.getPropertySource()
115                     , toscaGetFunction.getFunctionType())
116             );
117         if (toscaGetFunction.isSubProperty()) {
118             referredProperty = findSubProperty(referredProperty, toscaGetFunction, model);
119         }
120
121         if (!property.getType().equals(referredProperty.getType())) {
122             throw ToscaGetFunctionExceptionSupplier
123                 .propertyTypeDiverge(toscaGetFunction.getType(), referredProperty.getType(), property.getType()).get();
124         }
125         if (PropertyType.typeHasSchema(referredProperty.getType()) && !referredProperty.getSchemaType().equals(property.getSchemaType())) {
126             throw ToscaGetFunctionExceptionSupplier
127                 .propertySchemaDiverge(toscaGetFunction.getType(), referredProperty.getSchemaType(), property.getSchemaType()).get();
128         }
129     }
130
131     private void validateGetToscaFunctionAttributes(final ToscaGetFunctionDataDefinition toscaGetFunction) {
132         if (toscaGetFunction.getFunctionType() == null) {
133             throw ToscaGetFunctionExceptionSupplier.targetFunctionTypeNotFound().get();
134         }
135         if (toscaGetFunction.getPropertySource() == null) {
136             throw ToscaGetFunctionExceptionSupplier.targetPropertySourceNotFound(toscaGetFunction.getFunctionType()).get();
137         }
138         if (CollectionUtils.isEmpty(toscaGetFunction.getPropertyPathFromSource())) {
139             throw ToscaGetFunctionExceptionSupplier
140                 .targetSourcePathNotFound(toscaGetFunction.getFunctionType()).get();
141         }
142         if (StringUtils.isEmpty(toscaGetFunction.getSourceName()) || StringUtils.isBlank(toscaGetFunction.getSourceName())) {
143             throw ToscaGetFunctionExceptionSupplier.sourceNameNotFound(toscaGetFunction.getPropertySource()).get();
144         }
145         if (StringUtils.isEmpty(toscaGetFunction.getSourceUniqueId()) || StringUtils.isBlank(toscaGetFunction.getSourceUniqueId())) {
146             throw ToscaGetFunctionExceptionSupplier.sourceIdNotFound(toscaGetFunction.getPropertySource()).get();
147         }
148         if (StringUtils.isEmpty(toscaGetFunction.getPropertyName()) || StringUtils.isBlank(toscaGetFunction.getPropertyName())) {
149             throw ToscaGetFunctionExceptionSupplier.propertyNameNotFound(toscaGetFunction.getPropertySource()).get();
150         }
151         if (StringUtils.isEmpty(toscaGetFunction.getPropertyUniqueId()) || StringUtils.isBlank(toscaGetFunction.getPropertyUniqueId())) {
152             throw ToscaGetFunctionExceptionSupplier.propertyIdNotFound(toscaGetFunction.getPropertySource()).get();
153         }
154     }
155
156     private void validateGetPropertySource(final ToscaGetFunctionType functionType, final PropertySource propertySource) {
157         if (functionType == ToscaGetFunctionType.GET_INPUT && propertySource != PropertySource.SELF) {
158             throw ToscaGetFunctionExceptionSupplier
159                 .targetSourceNotSupported(functionType, propertySource).get();
160         }
161         if (functionType == ToscaGetFunctionType.GET_PROPERTY && !List.of(PropertySource.SELF, PropertySource.INSTANCE).contains(propertySource)) {
162             throw ToscaGetFunctionExceptionSupplier
163                 .targetSourceNotSupported(functionType, propertySource).get();
164         }
165     }
166
167     private ToscaPropertyData findSubProperty(final ToscaPropertyData referredProperty,
168                                               final ToscaGetFunctionDataDefinition toscaGetFunction,
169                                               final String model) {
170         final Map<String, DataTypeDefinition> dataTypeMap = loadDataTypes(model);
171         final List<String> propertyPathFromSource = toscaGetFunction.getPropertyPathFromSource();
172         DataTypeDefinition dataType = dataTypeMap.get(referredProperty.getType());
173         if (dataType == null) {
174             throw ToscaGetFunctionExceptionSupplier
175                 .propertyDataTypeNotFound(propertyPathFromSource.get(0), referredProperty.getType(), toscaGetFunction.getFunctionType()).get();
176         }
177         ToscaPropertyData foundProperty = referredProperty;
178         for (int i = 1; i < propertyPathFromSource.size(); i++) {
179             final String currentPropertyName = propertyPathFromSource.get(i);
180             foundProperty = dataType.getProperties().stream()
181                 .filter(propertyDefinition -> currentPropertyName.equals(propertyDefinition.getName())).findFirst()
182                 .orElseThrow(
183                     ToscaGetFunctionExceptionSupplier
184                         .propertyNotFoundOnTarget(propertyPathFromSource.subList(0, i), toscaGetFunction.getPropertySource(),
185                             toscaGetFunction.getFunctionType())
186                 );
187             dataType = dataTypeMap.get(foundProperty.getType());
188             if (dataType == null) {
189                 throw ToscaGetFunctionExceptionSupplier
190                     .propertyDataTypeNotFound(propertyPathFromSource.subList(0, i), foundProperty.getType(),
191                         toscaGetFunction.getFunctionType()).get();
192             }
193         }
194         return foundProperty;
195     }
196
197     private Map<String, DataTypeDefinition> loadDataTypes(String model) {
198         final Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypeEither =
199             applicationDataTypeCache.getAll(model);
200         if (dataTypeEither.isRight()) {
201             throw ToscaGetFunctionExceptionSupplier.couldNotLoadDataTypes(model).get();
202         }
203         return dataTypeEither.left().value();
204     }
205
206 }