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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * SPDX-License-Identifier: Apache-2.0
19 * ============LICENSE_END=========================================================
22 package org.openecomp.sdc.be.components.impl.validation;
24 import fj.data.Either;
25 import java.util.List;
27 import java.util.stream.Collectors;
28 import java.util.stream.Stream;
29 import org.apache.commons.collections.CollectionUtils;
30 import org.apache.commons.lang3.StringUtils;
31 import org.onap.sdc.tosca.datatypes.model.PropertyType;
32 import org.openecomp.sdc.be.components.impl.exceptions.ToscaFunctionExceptionSupplier;
33 import org.openecomp.sdc.be.components.impl.exceptions.ToscaGetFunctionExceptionSupplier;
34 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
35 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
36 import org.openecomp.sdc.be.datatypes.elements.ToscaGetFunctionDataDefinition;
37 import org.openecomp.sdc.be.datatypes.enums.PropertySource;
38 import org.openecomp.sdc.be.datatypes.tosca.ToscaGetFunctionType;
39 import org.openecomp.sdc.be.model.Component;
40 import org.openecomp.sdc.be.model.ComponentInstance;
41 import org.openecomp.sdc.be.model.DataTypeDefinition;
42 import org.openecomp.sdc.be.model.ToscaPropertyData;
43 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
44 import org.openecomp.sdc.be.model.validation.ToscaFunctionValidator;
46 @org.springframework.stereotype.Component
47 public class ToscaFunctionValidatorImpl implements ToscaFunctionValidator {
49 private final ApplicationDataTypeCache applicationDataTypeCache;
51 public ToscaFunctionValidatorImpl(final ApplicationDataTypeCache applicationDataTypeCache) {
52 this.applicationDataTypeCache = applicationDataTypeCache;
56 public <T extends PropertyDataDefinition> void validate(T property, final Component containerComponent) {
57 if (property.getToscaFunction().getType() == null) {
58 throw ToscaFunctionExceptionSupplier.missingFunctionType().get();
60 if (property.isToscaGetFunction()) {
61 validateToscaGetFunction(property, containerComponent);
65 private <T extends PropertyDataDefinition> void validateToscaGetFunction(T property, Component parentComponent) {
66 final ToscaGetFunctionDataDefinition toscaGetFunction = (ToscaGetFunctionDataDefinition) property.getToscaFunction();
67 validateGetToscaFunctionAttributes(toscaGetFunction);
68 final ToscaGetFunctionType functionType = toscaGetFunction.getFunctionType();
69 validateGetPropertySource(functionType, toscaGetFunction.getPropertySource());
70 final String model = parentComponent.getModel();
71 switch (functionType) {
73 validateGetFunction(property, parentComponent.getInputs(), model);
76 if (toscaGetFunction.getPropertySource() == PropertySource.SELF) {
77 validateGetFunction(property, parentComponent.getProperties(), model);
78 } else if (toscaGetFunction.getPropertySource() == PropertySource.INSTANCE) {
79 final ComponentInstance componentInstance =
80 parentComponent.getComponentInstanceById(toscaGetFunction.getSourceUniqueId())
81 .orElseThrow(ToscaGetFunctionExceptionSupplier.instanceNotFound(toscaGetFunction.getSourceName()));
82 validateGetFunction(property, componentInstance.getProperties(), model);
86 if (toscaGetFunction.getPropertySource() == PropertySource.SELF) {
87 validateGetFunction(property, combine(parentComponent.getProperties(), parentComponent.getAttributes()), model);
88 } else if (toscaGetFunction.getPropertySource() == PropertySource.INSTANCE) {
89 final ComponentInstance componentInstance = parentComponent.getComponentInstanceById(toscaGetFunction.getSourceUniqueId())
90 .orElseThrow(ToscaGetFunctionExceptionSupplier.instanceNotFound(toscaGetFunction.getSourceName()));
91 validateGetFunction(property, combine(componentInstance.getProperties(), componentInstance.getAttributes()), model);
95 throw ToscaGetFunctionExceptionSupplier.functionNotSupported(functionType).get();
99 private List<? extends ToscaPropertyData> combine(final List<? extends ToscaPropertyData> parentProperties,
100 final List<? extends ToscaPropertyData> parentAttributes) {
101 if (CollectionUtils.isNotEmpty(parentProperties) && CollectionUtils.isNotEmpty(parentAttributes)) {
102 return Stream.concat(parentProperties.stream(), parentAttributes.stream()).collect(Collectors.toList());
104 if (CollectionUtils.isEmpty(parentProperties)) {
105 return parentAttributes;
107 return parentProperties;
110 private <T extends PropertyDataDefinition> void validateGetFunction(final T property,
111 final List<? extends ToscaPropertyData> parentProperties,
112 final String model) {
113 final ToscaGetFunctionDataDefinition toscaGetFunction = (ToscaGetFunctionDataDefinition) property.getToscaFunction();
114 if (CollectionUtils.isEmpty(parentProperties)) {
115 throw ToscaGetFunctionExceptionSupplier
116 .propertyNotFoundOnTarget(toscaGetFunction.getPropertyName(), toscaGetFunction.getPropertySource(),
117 toscaGetFunction.getFunctionType()
120 final String getFunctionPropertyUniqueId = toscaGetFunction.getPropertyUniqueId();
121 ToscaPropertyData referredProperty = parentProperties.stream()
122 .filter(property1 -> getFunctionPropertyUniqueId.equals(property1.getUniqueId()))
124 .orElseThrow(ToscaGetFunctionExceptionSupplier
125 .propertyNotFoundOnTarget(toscaGetFunction.getPropertyName(), toscaGetFunction.getPropertySource()
126 , toscaGetFunction.getFunctionType())
128 if (toscaGetFunction.isSubProperty()) {
129 referredProperty = findSubProperty(referredProperty, toscaGetFunction, model);
132 if (!property.getType().equals(referredProperty.getType()) && !"list".equalsIgnoreCase(referredProperty.getType())) {
133 throw ToscaGetFunctionExceptionSupplier
134 .propertyTypeDiverge(toscaGetFunction.getType(), referredProperty.getType(), property.getType()).get();
136 if (PropertyType.typeHasSchema(referredProperty.getType()) && !referredProperty.getSchemaType().equals(property.getType()) && !"list".equalsIgnoreCase(referredProperty.getType()) && !referredProperty.getSchemaType().equals(property.getSchemaType())) {
137 throw ToscaGetFunctionExceptionSupplier
138 .propertySchemaDiverge(toscaGetFunction.getType(), referredProperty.getSchemaType(), property.getSchemaType()).get();
142 private void validateGetToscaFunctionAttributes(final ToscaGetFunctionDataDefinition toscaGetFunction) {
143 if (toscaGetFunction.getFunctionType() == null) {
144 throw ToscaGetFunctionExceptionSupplier.targetFunctionTypeNotFound().get();
146 if (toscaGetFunction.getPropertySource() == null) {
147 throw ToscaGetFunctionExceptionSupplier.targetPropertySourceNotFound(toscaGetFunction.getFunctionType()).get();
149 if (CollectionUtils.isEmpty(toscaGetFunction.getPropertyPathFromSource())) {
150 throw ToscaGetFunctionExceptionSupplier
151 .targetSourcePathNotFound(toscaGetFunction.getFunctionType()).get();
153 if (StringUtils.isEmpty(toscaGetFunction.getSourceName()) || StringUtils.isBlank(toscaGetFunction.getSourceName())) {
154 throw ToscaGetFunctionExceptionSupplier.sourceNameNotFound(toscaGetFunction.getPropertySource()).get();
156 if (StringUtils.isEmpty(toscaGetFunction.getSourceUniqueId()) || StringUtils.isBlank(toscaGetFunction.getSourceUniqueId())) {
157 throw ToscaGetFunctionExceptionSupplier.sourceIdNotFound(toscaGetFunction.getPropertySource()).get();
159 if (StringUtils.isEmpty(toscaGetFunction.getPropertyName()) || StringUtils.isBlank(toscaGetFunction.getPropertyName())) {
160 throw ToscaGetFunctionExceptionSupplier.propertyNameNotFound(toscaGetFunction.getPropertySource()).get();
162 if (StringUtils.isEmpty(toscaGetFunction.getPropertyUniqueId()) || StringUtils.isBlank(toscaGetFunction.getPropertyUniqueId())) {
163 throw ToscaGetFunctionExceptionSupplier.propertyIdNotFound(toscaGetFunction.getPropertySource()).get();
167 private void validateGetPropertySource(final ToscaGetFunctionType functionType, final PropertySource propertySource) {
168 if (functionType == ToscaGetFunctionType.GET_INPUT && propertySource != PropertySource.SELF) {
169 throw ToscaGetFunctionExceptionSupplier
170 .targetSourceNotSupported(functionType, propertySource).get();
172 if (functionType == ToscaGetFunctionType.GET_PROPERTY && !List.of(PropertySource.SELF, PropertySource.INSTANCE).contains(propertySource)) {
173 throw ToscaGetFunctionExceptionSupplier
174 .targetSourceNotSupported(functionType, propertySource).get();
178 private ToscaPropertyData findSubProperty(final ToscaPropertyData referredProperty,
179 final ToscaGetFunctionDataDefinition toscaGetFunction,
180 final String model) {
181 final Map<String, DataTypeDefinition> dataTypeMap = loadDataTypes(model);
182 final List<String> propertyPathFromSource = toscaGetFunction.getPropertyPathFromSource();
183 DataTypeDefinition dataType = dataTypeMap.get(referredProperty.getType());
184 if (dataType == null) {
185 throw ToscaGetFunctionExceptionSupplier
186 .propertyDataTypeNotFound(propertyPathFromSource.get(0), referredProperty.getType(), toscaGetFunction.getFunctionType()).get();
188 ToscaPropertyData foundProperty = referredProperty;
189 for (int i = 1; i < propertyPathFromSource.size(); i++) {
190 final String currentPropertyName = propertyPathFromSource.get(i);
191 foundProperty = dataType.getProperties().stream()
192 .filter(propertyDefinition -> currentPropertyName.equals(propertyDefinition.getName())).findFirst()
194 ToscaGetFunctionExceptionSupplier
195 .propertyNotFoundOnTarget(propertyPathFromSource.subList(0, i), toscaGetFunction.getPropertySource(),
196 toscaGetFunction.getFunctionType())
198 dataType = dataTypeMap.get(foundProperty.getType());
199 if (dataType == null) {
200 throw ToscaGetFunctionExceptionSupplier
201 .propertyDataTypeNotFound(propertyPathFromSource.subList(0, i), foundProperty.getType(),
202 toscaGetFunction.getFunctionType()).get();
205 return foundProperty;
208 private Map<String, DataTypeDefinition> loadDataTypes(String model) {
209 final Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> dataTypeEither =
210 applicationDataTypeCache.getAll(model);
211 if (dataTypeEither.isRight()) {
212 throw ToscaGetFunctionExceptionSupplier.couldNotLoadDataTypes(model).get();
214 return dataTypeEither.left().value();