Support TOSCA functions in Node Filters
[sdc.git] / common-be / src / main / java / org / openecomp / sdc / be / utils / PropertyFilterConstraintDataDefinitionHelper.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.utils;
23
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Optional;
27 import java.util.Set;
28 import lombok.AccessLevel;
29 import lombok.NoArgsConstructor;
30 import org.openecomp.sdc.be.datatypes.elements.PropertyFilterConstraintDataDefinition;
31 import org.openecomp.sdc.be.datatypes.elements.ToscaConcatFunction;
32 import org.openecomp.sdc.be.datatypes.elements.ToscaFunction;
33 import org.openecomp.sdc.be.datatypes.elements.ToscaFunctionParameter;
34 import org.openecomp.sdc.be.datatypes.elements.ToscaFunctionType;
35 import org.openecomp.sdc.be.datatypes.elements.ToscaGetFunctionDataDefinition;
36 import org.openecomp.sdc.be.datatypes.elements.ToscaStringParameter;
37 import org.openecomp.sdc.be.datatypes.enums.ConstraintType;
38 import org.openecomp.sdc.be.datatypes.enums.FilterValueType;
39 import org.openecomp.sdc.be.datatypes.enums.PropertyFilterTargetType;
40 import org.openecomp.sdc.be.datatypes.enums.PropertySource;
41 import org.openecomp.sdc.be.datatypes.tosca.ToscaGetFunctionType;
42 import org.openecomp.sdc.exception.InvalidArgumentException;
43 import org.yaml.snakeyaml.Yaml;
44
45 @NoArgsConstructor(access = AccessLevel.PRIVATE)
46 public class PropertyFilterConstraintDataDefinitionHelper {
47
48     public static PropertyFilterConstraintDataDefinition convertLegacyConstraint(final String constraint) {
49         final var propertyFilterConstraint = new PropertyFilterConstraintDataDefinition();
50         final Map<String, Object> constraintYaml = new Yaml().load(constraint);
51         final String propertyName = constraintYaml.keySet().iterator().next();
52         propertyFilterConstraint.setPropertyName(propertyName);
53         final Map<String, Object> operatorYaml = (Map<String, Object>) constraintYaml.get(propertyName);
54         final String operator = operatorYaml.keySet().iterator().next();
55         propertyFilterConstraint.setOperator(ConstraintType.findByType(operator).orElse(null));
56         final Object valueYaml = operatorYaml.get(operator);
57         final Optional<ToscaFunction> toscaFunction = createToscaFunctionFromLegacyConstraintValue(valueYaml);
58         if (toscaFunction.isPresent()) {
59             propertyFilterConstraint.setValue(toscaFunction.get());
60         } else {
61             propertyFilterConstraint.setValue(valueYaml);
62         }
63         propertyFilterConstraint.setValueType(detectValueType(valueYaml));
64         propertyFilterConstraint.setTargetType(PropertyFilterTargetType.PROPERTY);
65         return propertyFilterConstraint;
66     }
67
68     public static Optional<ToscaFunction> createToscaFunctionFromLegacyConstraintValue(final Object filterValue) {
69         if (!(filterValue instanceof Map)) {
70             return Optional.empty();
71         }
72         final Map<?, ?> filterValueAsMap = (Map<?, ?>) filterValue;
73         final Set<?> keys = filterValueAsMap.keySet();
74         if (keys.size() != 1) {
75             return Optional.empty();
76         }
77         final Object toscaFunctionTypeObject = keys.iterator().next();
78         if (!(toscaFunctionTypeObject instanceof String)) {
79             return Optional.empty();
80         }
81         final ToscaFunctionType toscaFunctionType = ToscaFunctionType.findType((String) toscaFunctionTypeObject).orElse(null);
82         if (toscaFunctionType == null) {
83             return Optional.empty();
84         }
85         switch (toscaFunctionType) {
86             case GET_INPUT:
87                 return readLegacyGetInputConstraintValue(filterValueAsMap, toscaFunctionTypeObject);
88             case GET_ATTRIBUTE:
89             case GET_PROPERTY:
90                 return readLegacyGetPropertyConstraintValue(filterValueAsMap, toscaFunctionTypeObject, toscaFunctionType);
91             case CONCAT:
92                 return readLegacyConcatConstraintValue(filterValueAsMap, toscaFunctionTypeObject);
93             default:
94                 return Optional.empty();
95         }
96     }
97
98     public static Optional<FilterValueType> convertFromToscaFunctionType(final ToscaFunctionType toscaFunctionType) {
99         return FilterValueType.findByName(toscaFunctionType.getName());
100     }
101
102     private static Optional<ToscaFunction> readLegacyConcatConstraintValue(Map<?, ?> filterValueAsMap, Object toscaFunctionType) {
103         final List<Object> concatValue;
104         try {
105             concatValue = (List<Object>) filterValueAsMap.get(toscaFunctionType);
106         } catch (final Exception ignored) {
107             return Optional.empty();
108         }
109         if (concatValue.isEmpty()) {
110             return Optional.empty();
111         }
112         final var toscaConcatFunction = new ToscaConcatFunction();
113         for (Object parameter : concatValue) {
114             if (parameter instanceof String) {
115                 final ToscaStringParameter toscaStringParameter = new ToscaStringParameter();
116                 toscaStringParameter.setValue((String) parameter);
117                 toscaConcatFunction.addParameter(toscaStringParameter);
118             } else {
119                 createToscaFunctionFromLegacyConstraintValue(parameter)
120                     .ifPresent(toscaFunction -> toscaConcatFunction.addParameter((ToscaFunctionParameter) toscaFunction));
121             }
122         }
123         return Optional.of(toscaConcatFunction);
124     }
125
126     private static Optional<ToscaFunction> readLegacyGetPropertyConstraintValue(Map<?, ?> filterValueAsMap, Object toscaFunctionType,
127                                                                                 ToscaFunctionType toscaFunctionType1) {
128         final var toscaGetFunction = new ToscaGetFunctionDataDefinition();
129         toscaGetFunction.setFunctionType(ToscaGetFunctionType.fromToscaFunctionType(toscaFunctionType1)
130             .orElseThrow(() -> new InvalidArgumentException("Could not convert a ToscaFunctionType to a ToscaGetFunctionType"))
131         );
132         final List<String> getFunctionValue;
133         try {
134             getFunctionValue = (List<String>) filterValueAsMap.get(toscaFunctionType);
135         } catch (final Exception ignored) {
136             return Optional.of(toscaGetFunction);
137         }
138         if (!getFunctionValue.isEmpty()) {
139             final Optional<PropertySource> propertySource = PropertySource.findType(getFunctionValue.get(0));
140             if (propertySource.isPresent()) {
141                 toscaGetFunction.setPropertySource(propertySource.get());
142             } else {
143                 toscaGetFunction.setPropertySource(PropertySource.INSTANCE);
144                 toscaGetFunction.setSourceName(getFunctionValue.get(0));
145             }
146             final List<String> propertyPathFromSource = getFunctionValue.subList(1, getFunctionValue.size());
147             toscaGetFunction.setPropertyPathFromSource(propertyPathFromSource);
148             toscaGetFunction.setPropertyName(propertyPathFromSource.get(propertyPathFromSource.size() - 1));
149         }
150         return Optional.of(toscaGetFunction);
151     }
152
153     private static Optional<ToscaFunction> readLegacyGetInputConstraintValue(Map<?, ?> filterValueAsMap, Object toscaFunctionType) {
154         final var toscaGetFunction = new ToscaGetFunctionDataDefinition();
155         toscaGetFunction.setFunctionType(ToscaGetFunctionType.GET_INPUT);
156         final List<String> getFunctionValue;
157         final Object valueAsObject = filterValueAsMap.get(toscaFunctionType);
158         if (valueAsObject instanceof String) {
159             getFunctionValue = List.of((String) valueAsObject);
160         } else if (valueAsObject instanceof List) {
161             try {
162                 getFunctionValue = (List<String>) filterValueAsMap.get(toscaFunctionType);
163             } catch (final Exception ignored) {
164                 return Optional.empty();
165             }
166         } else {
167             return Optional.empty();
168         }
169
170         toscaGetFunction.setPropertyPathFromSource(getFunctionValue);
171         if (!getFunctionValue.isEmpty()) {
172             toscaGetFunction.setPropertyName(getFunctionValue.get(getFunctionValue.size() - 1));
173         }
174         toscaGetFunction.setPropertySource(PropertySource.SELF);
175         return Optional.of(toscaGetFunction);
176     }
177
178     private static FilterValueType detectValueType(final Object value) {
179         if (value instanceof Map) {
180             final Map<?, ?> valueAsMap = (Map<?, ?>) value;
181             if (valueAsMap.containsKey(ToscaFunctionType.CONCAT.getName())) {
182                 return FilterValueType.CONCAT;
183             }
184             if (valueAsMap.containsKey(ToscaFunctionType.GET_ATTRIBUTE.getName())) {
185                 return FilterValueType.GET_ATTRIBUTE;
186             }
187             if (valueAsMap.containsKey(ToscaFunctionType.GET_PROPERTY.getName())) {
188                 return FilterValueType.GET_PROPERTY;
189             }
190             if (valueAsMap.containsKey(ToscaFunctionType.GET_INPUT.getName())) {
191                 return FilterValueType.GET_INPUT;
192             }
193         }
194
195         return FilterValueType.STATIC;
196     }
197
198 }