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.ToscaFunction;
31 import org.openecomp.sdc.be.datatypes.elements.ToscaFunctionParameter;
32 import org.openecomp.sdc.be.datatypes.elements.ToscaFunctionType;
33 import org.openecomp.sdc.be.datatypes.elements.ToscaGetFunctionDataDefinition;
34 import org.openecomp.sdc.be.datatypes.elements.ToscaStringParameter;
35 import org.openecomp.sdc.be.datatypes.enums.PropertySource;
36 import org.openecomp.sdc.be.datatypes.tosca.ToscaGetFunctionType;
38 @org.springframework.stereotype.Component
39 public class ToscaFunctionYamlParsingHandler {
42 * Builds a {@link ToscaFunction} based on the property value. It will build the object with the maximum information available in the property
43 * value, as not all the necessary information can be extracted from it. It will only parse values from supported functions in
44 * {@link ToscaFunctionType}.
46 * @param toscaFunctionPropertyValueMap the value of a property calls a TOSCA function
47 * @return the partially filled {@link ToscaFunction} object
49 public Optional<ToscaFunction> buildToscaFunctionBasedOnPropertyValue(final Map<String, Object> toscaFunctionPropertyValueMap) {
50 if (!isPropertyValueToscaFunction(toscaFunctionPropertyValueMap)) {
51 return Optional.empty();
53 final String functionType = toscaFunctionPropertyValueMap.keySet().iterator().next();
54 final ToscaFunctionType toscaFunctionType = ToscaFunctionType.findType(functionType).orElse(null);
55 if (toscaFunctionType == null) {
56 return Optional.empty();
58 switch (toscaFunctionType) {
60 return handleGetInputFunction(toscaFunctionPropertyValueMap, functionType);
64 return handleGetPropertyFunction(toscaFunctionPropertyValueMap, functionType, toscaFunctionType);
67 return handleConcatFunction(toscaFunctionPropertyValueMap, functionType);
69 return Optional.empty();
74 * Checks if the property value is a supported TOSCA function.
76 * @param propValueObj the value of a property
77 * @return {@code true} if the value is a supported TOSCA function, {@code false} otherwise
79 public boolean isPropertyValueToscaFunction(final Object propValueObj) {
80 if (propValueObj instanceof Map) {
81 final Map<String, Object> propValueMap = (Map<String, Object>) propValueObj;
82 if (propValueMap.keySet().size() > 1) {
85 return Stream.of(ToscaFunctionType.GET_INPUT, ToscaFunctionType.GET_PROPERTY, ToscaFunctionType.GET_ATTRIBUTE, ToscaFunctionType.CONCAT)
86 .anyMatch(type -> propValueMap.containsKey(type.getName()));
91 private Optional<ToscaFunction> handleConcatFunction(Map<String, Object> toscaFunctionPropertyValueMap, String functionType) {
92 final ToscaConcatFunction toscaConcatFunction = new ToscaConcatFunction();
93 final Object functionValueObj = toscaFunctionPropertyValueMap.get(functionType);
94 if (!(functionValueObj instanceof List)) {
95 return Optional.empty();
97 final List<Object> functionParameters = (List<Object>) functionValueObj;
98 if (functionParameters.size() < 2) {
99 return Optional.empty();
101 functionParameters.forEach(parameter -> {
102 if (parameter instanceof String) {
103 final var stringParameter = new ToscaStringParameter();
104 stringParameter.setValue((String) parameter);
105 toscaConcatFunction.addParameter(stringParameter);
108 if (isPropertyValueToscaFunction(parameter)) {
109 buildToscaFunctionBasedOnPropertyValue((Map<String, Object>) parameter).ifPresent(toscaFunction -> {
110 if (toscaFunction instanceof ToscaFunctionParameter) {
111 toscaConcatFunction.addParameter((ToscaFunctionParameter) toscaFunction);
116 final var customYamlFunction = new CustomYamlFunction();
117 customYamlFunction.setYamlValue(parameter);
118 toscaConcatFunction.addParameter(customYamlFunction);
120 return Optional.of(toscaConcatFunction);
123 private static Optional<ToscaFunction> handleGetPropertyFunction(Map<String, Object> toscaFunctionPropertyValueMap, String functionType,
124 ToscaFunctionType toscaFunctionType) {
125 final ToscaGetFunctionDataDefinition toscaGetFunction = new ToscaGetFunctionDataDefinition();
126 toscaGetFunction.setFunctionType(
127 toscaFunctionType == ToscaFunctionType.GET_PROPERTY ? ToscaGetFunctionType.GET_PROPERTY : ToscaGetFunctionType.GET_ATTRIBUTE
129 final Object functionValueObj = toscaFunctionPropertyValueMap.get(functionType);
130 if (!(functionValueObj instanceof List)) {
131 return Optional.empty();
133 final List<String> functionParameters;
135 functionParameters = (List<String>) functionValueObj;
136 } catch (final ClassCastException ignored) {
137 return Optional.empty();
139 if (functionParameters.size() < 2) {
140 return Optional.empty();
142 final String propertySourceType = functionParameters.get(0);
143 final PropertySource propertySource = PropertySource.findType(propertySourceType).orElse(null);
144 if (propertySource == PropertySource.SELF) {
145 toscaGetFunction.setPropertySource(propertySource);
147 toscaGetFunction.setPropertySource(PropertySource.INSTANCE);
148 toscaGetFunction.setSourceName(propertySourceType);
150 toscaGetFunction.setPropertyPathFromSource(functionParameters.subList(1, functionParameters.size()));
151 final String propertyName = toscaGetFunction.getPropertyPathFromSource().get(toscaGetFunction.getPropertyPathFromSource().size() - 1);
152 toscaGetFunction.setPropertyName(propertyName);
153 return Optional.of(toscaGetFunction);
156 private static Optional<ToscaFunction> handleGetInputFunction(Map<String, Object> toscaFunctionPropertyValueMap, String functionType) {
157 final ToscaGetFunctionDataDefinition toscaGetFunction = new ToscaGetFunctionDataDefinition();
158 toscaGetFunction.setFunctionType(ToscaGetFunctionType.GET_INPUT);
159 toscaGetFunction.setPropertySource(PropertySource.SELF);
160 final Object functionValueObj = toscaFunctionPropertyValueMap.get(functionType);
161 if (!(functionValueObj instanceof List) && !(functionValueObj instanceof String)) {
162 return Optional.empty();
164 if (functionValueObj instanceof String) {
165 toscaGetFunction.setPropertyPathFromSource(List.of((String) functionValueObj));
167 final List<String> functionParameters;
169 functionParameters = (List<String>) functionValueObj;
170 } catch (final ClassCastException ignored) {
171 return Optional.empty();
173 toscaGetFunction.setPropertyPathFromSource(functionParameters);
175 final String propertyName = toscaGetFunction.getPropertyPathFromSource().get(toscaGetFunction.getPropertyPathFromSource().size() - 1);
176 toscaGetFunction.setPropertyName(propertyName);
177 return Optional.of(toscaGetFunction);