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.csar;
24 import java.util.List;
26 import java.util.Optional;
27 import java.util.stream.Stream;
28 import org.openecomp.sdc.be.datatypes.elements.CustomYamlFunction;
29 import org.openecomp.sdc.be.datatypes.elements.ToscaConcatFunction;
30 import org.openecomp.sdc.be.datatypes.elements.ToscaCustomFunction;
31 import org.openecomp.sdc.be.datatypes.elements.ToscaFunction;
32 import org.openecomp.sdc.be.datatypes.elements.ToscaFunctionParameter;
33 import org.openecomp.sdc.be.datatypes.elements.ToscaFunctionType;
34 import org.openecomp.sdc.be.datatypes.elements.ToscaGetFunctionDataDefinition;
35 import org.openecomp.sdc.be.datatypes.elements.ToscaStringParameter;
36 import org.openecomp.sdc.be.datatypes.enums.PropertySource;
37 import org.openecomp.sdc.be.datatypes.tosca.ToscaGetFunctionType;
39 @org.springframework.stereotype.Component
40 public class ToscaFunctionYamlParsingHandler {
42 private static Optional<ToscaFunction> handleGetPropertyFunction(Map<String, Object> toscaFunctionPropertyValueMap, String functionType,
43 ToscaFunctionType toscaFunctionType) {
44 final ToscaGetFunctionDataDefinition toscaGetFunction = new ToscaGetFunctionDataDefinition();
45 toscaGetFunction.setFunctionType(
46 toscaFunctionType == ToscaFunctionType.GET_PROPERTY ? ToscaGetFunctionType.GET_PROPERTY : ToscaGetFunctionType.GET_ATTRIBUTE
48 final Object functionValueObj = toscaFunctionPropertyValueMap.get(functionType);
49 if (!(functionValueObj instanceof List)) {
50 return Optional.empty();
52 final List<String> functionParameters;
54 functionParameters = (List<String>) functionValueObj;
55 } catch (final ClassCastException ignored) {
56 return Optional.empty();
58 if (functionParameters.size() < 2) {
59 return Optional.empty();
61 final String propertySourceType = functionParameters.get(0);
62 final PropertySource propertySource = PropertySource.findType(propertySourceType).orElse(null);
63 if (propertySource == PropertySource.SELF) {
64 toscaGetFunction.setPropertySource(propertySource);
66 toscaGetFunction.setPropertySource(PropertySource.INSTANCE);
67 toscaGetFunction.setSourceName(propertySourceType);
69 toscaGetFunction.setPropertyPathFromSource(functionParameters.subList(1, functionParameters.size()));
70 final String propertyName = toscaGetFunction.getPropertyPathFromSource().get(toscaGetFunction.getPropertyPathFromSource().size() - 1);
71 toscaGetFunction.setPropertyName(propertyName);
72 return Optional.of(toscaGetFunction);
75 private static Optional<ToscaFunction> handleGetInputFunction(Map<String, Object> toscaFunctionPropertyValueMap, String functionType) {
76 final ToscaGetFunctionDataDefinition toscaGetFunction = new ToscaGetFunctionDataDefinition();
77 toscaGetFunction.setFunctionType(ToscaGetFunctionType.GET_INPUT);
78 toscaGetFunction.setPropertySource(PropertySource.SELF);
79 final Object functionValueObj = toscaFunctionPropertyValueMap.get(functionType);
80 if (!(functionValueObj instanceof List) && !(functionValueObj instanceof String)) {
81 return Optional.empty();
83 if (functionValueObj instanceof String) {
84 toscaGetFunction.setPropertyPathFromSource(List.of((String) functionValueObj));
86 final List<String> functionParameters;
88 functionParameters = (List<String>) functionValueObj;
89 } catch (final ClassCastException ignored) {
90 return Optional.empty();
92 toscaGetFunction.setPropertyPathFromSource(functionParameters);
94 final String propertyName = toscaGetFunction.getPropertyPathFromSource().get(toscaGetFunction.getPropertyPathFromSource().size() - 1);
95 toscaGetFunction.setPropertyName(propertyName);
96 return Optional.of(toscaGetFunction);
100 * Builds a {@link ToscaFunction} based on the property value. It will build the object with the maximum information available in the property
101 * value, as not all the necessary information can be extracted from it. It will only parse values from supported functions in
102 * {@link ToscaFunctionType}.
104 * @param toscaFunctionPropertyValueMap the value of a property calls a TOSCA function
105 * @return the partially filled {@link ToscaFunction} object
107 public Optional<ToscaFunction> buildToscaFunctionBasedOnPropertyValue(final Map<String, Object> toscaFunctionPropertyValueMap) {
108 if (!isPropertyValueToscaFunction(toscaFunctionPropertyValueMap)) {
109 return Optional.empty();
111 final String functionType = toscaFunctionPropertyValueMap.keySet().iterator().next();
112 final ToscaFunctionType toscaFunctionType =
113 ToscaFunctionType.findType(functionType).orElse(functionType.startsWith("$") ? ToscaFunctionType.CUSTOM : null);
114 if (toscaFunctionType == null) {
115 return Optional.empty();
117 switch (toscaFunctionType) {
119 return handleGetInputFunction(toscaFunctionPropertyValueMap, functionType);
122 case GET_ATTRIBUTE: {
123 return handleGetPropertyFunction(toscaFunctionPropertyValueMap, functionType, toscaFunctionType);
126 return handleConcatFunction(toscaFunctionPropertyValueMap, functionType);
128 return handleCustomFunction(toscaFunctionPropertyValueMap, functionType);
130 return Optional.empty();
134 private Optional<ToscaFunction> handleCustomFunction(Map<String, Object> toscaFunctionPropertyValueMap, String functionType) {
135 final ToscaCustomFunction toscaCustomFunction = new ToscaCustomFunction();
136 toscaCustomFunction.setName(functionType.substring(1));
137 final Object functionValueObj = toscaFunctionPropertyValueMap.get(functionType);
138 if (!(functionValueObj instanceof List)) {
139 return Optional.empty();
141 final List<Object> functionParameters = (List<Object>) functionValueObj;
142 functionParameters.forEach(parameter -> {
143 if (parameter instanceof String) {
144 final var stringParameter = new ToscaStringParameter();
145 stringParameter.setValue((String) parameter);
146 toscaCustomFunction.addParameter(stringParameter);
149 if (isPropertyValueToscaFunction(parameter)) {
150 buildToscaFunctionBasedOnPropertyValue((Map<String, Object>) parameter).ifPresent(toscaFunction -> {
151 if (toscaFunction instanceof ToscaFunctionParameter) {
152 toscaCustomFunction.addParameter((ToscaFunctionParameter) toscaFunction);
157 final var customYamlFunction = new CustomYamlFunction();
158 customYamlFunction.setYamlValue(parameter);
159 toscaCustomFunction.addParameter(customYamlFunction);
161 return Optional.of(toscaCustomFunction);
165 * Checks if the property value is a supported TOSCA function.
167 * @param propValueObj the value of a property
168 * @return {@code true} if the value is a supported TOSCA function, {@code false} otherwise
170 public boolean isPropertyValueToscaFunction(final Object propValueObj) {
171 if (propValueObj instanceof Map) {
172 final Map<String, Object> propValueMap = (Map<String, Object>) propValueObj;
173 if (propValueMap.keySet().size() > 1) {
176 if (propValueMap.keySet().stream().anyMatch(keyValue -> keyValue.startsWith("$"))) {
180 return Stream.of(ToscaFunctionType.GET_INPUT, ToscaFunctionType.GET_PROPERTY, ToscaFunctionType.GET_ATTRIBUTE, ToscaFunctionType.CONCAT)
181 .anyMatch(type -> propValueMap.containsKey(type.getName()));
186 private Optional<ToscaFunction> handleConcatFunction(Map<String, Object> toscaFunctionPropertyValueMap, String functionType) {
187 final ToscaConcatFunction toscaConcatFunction = new ToscaConcatFunction();
188 final Object functionValueObj = toscaFunctionPropertyValueMap.get(functionType);
189 if (!(functionValueObj instanceof List)) {
190 return Optional.empty();
192 final List<Object> functionParameters = (List<Object>) functionValueObj;
193 if (functionParameters.size() < 2) {
194 return Optional.empty();
196 functionParameters.forEach(parameter -> {
197 if (parameter instanceof String) {
198 final var stringParameter = new ToscaStringParameter();
199 stringParameter.setValue((String) parameter);
200 toscaConcatFunction.addParameter(stringParameter);
203 if (isPropertyValueToscaFunction(parameter)) {
204 buildToscaFunctionBasedOnPropertyValue((Map<String, Object>) parameter).ifPresent(toscaFunction -> {
205 if (toscaFunction instanceof ToscaFunctionParameter) {
206 toscaConcatFunction.addParameter((ToscaFunctionParameter) toscaFunction);
211 final var customYamlFunction = new CustomYamlFunction();
212 customYamlFunction.setYamlValue(parameter);
213 toscaConcatFunction.addParameter(customYamlFunction);
215 return Optional.of(toscaConcatFunction);