Support TOSCA functions in Node Filters
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / impl / ServiceFilterUtils.java
1 /*
2  * Copyright © 2016-2018 European Support Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.openecomp.sdc.be.impl;
17
18 import java.util.List;
19 import java.util.Map;
20 import java.util.Set;
21 import java.util.function.Function;
22 import java.util.stream.Collectors;
23 import org.apache.commons.collections.CollectionUtils;
24 import org.javatuples.Pair;
25 import org.openecomp.sdc.be.datamodel.utils.ConstraintConvertor;
26 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
27 import org.openecomp.sdc.be.datatypes.elements.PropertyFilterConstraintDataDefinition;
28 import org.openecomp.sdc.be.datatypes.elements.PropertyFilterDataDefinition;
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.enums.FilterValueType;
35 import org.openecomp.sdc.be.model.ComponentInstance;
36 import org.openecomp.sdc.be.model.InputDefinition;
37 import org.openecomp.sdc.be.model.Service;
38 import org.openecomp.sdc.be.ui.mapper.FilterConstraintMapper;
39
40 public class ServiceFilterUtils {
41
42     private ServiceFilterUtils() {
43     }
44
45     public static boolean isNodeFilterAffectedByPropertyRemoval(Service service, String ciName, String propertyName) {
46         return service.getComponentInstances().stream().filter(ci -> ci.getNodeFilter() != null)
47             .anyMatch(ci -> propertyIsUsedInCI(ci, ciName, propertyName));
48     }
49
50     private static boolean propertyIsUsedInCI(ComponentInstance ci, String ciName, String propertyName) {
51         if (CollectionUtils.isEmpty(ci.getDirectives())) {
52             return false;
53         }
54         if (ci.getNodeFilter() == null || ci.getNodeFilter().getProperties() == null
55             || ci.getNodeFilter().getProperties().getListToscaDataDefinition() == null) {
56             return false;
57         }
58         return ci.getNodeFilter().getProperties().getListToscaDataDefinition().stream()
59             .flatMap(prop -> prop.getConstraints().stream())
60             .filter(constraint ->
61                 List.of(ConstraintConvertor.PROPERTY_CONSTRAINT, ToscaFunctionType.GET_PROPERTY.getName())
62                     .contains(constraint.getValueType().getName())
63             )
64             .map(new FilterConstraintMapper()::mapFrom)
65             .anyMatch(constraint -> {
66                 final ToscaGetFunctionDataDefinition toscaGetFunction = constraint.getAsToscaGetFunction().orElse(null);
67                 if (toscaGetFunction == null) {
68                     return false;
69                 }
70                 return toscaGetFunction.getSourceName().equals(ciName) && toscaGetFunction.getPropertyPathFromSource().contains(propertyName);
71             });
72     }
73
74     public static Map<String, CINodeFilterDataDefinition> getRenamedNodesFilter(Service service, String oldName, String newName) {
75         return service.getComponentInstances().stream().filter(ci -> isNodeFilterUsingChangedCi(ci, oldName))
76             .map(ci -> renameOldCiNames(ci, oldName, newName)).collect(Collectors.toMap(Pair::getValue0, Pair::getValue1));
77     }
78
79     private static Pair<String, CINodeFilterDataDefinition> renameOldCiNames(ComponentInstance ci, String oldName, String newName) {
80         ci.getNodeFilter().getProperties().getListToscaDataDefinition().stream()
81             .filter(property -> isPropertyConstraintChangedByCi(property, oldName))
82             .forEach(property -> renamePropertyCiNames(property, oldName, newName));
83         return new Pair<>(ci.getUniqueId(), ci.getNodeFilter());
84     }
85
86     private static void renamePropertyCiNames(final PropertyFilterDataDefinition propertyFilter, final String oldInstanceName,
87                                               final String newInstanceName) {
88         final List<FilterValueType> instanceValueTypes =
89             List.of(FilterValueType.GET_PROPERTY, FilterValueType.GET_ATTRIBUTE, FilterValueType.CONCAT);
90         final List<PropertyFilterConstraintDataDefinition> constraints = propertyFilter.getConstraints().stream()
91             .filter(propertyFilter1 -> instanceValueTypes.contains(propertyFilter1.getValueType()))
92             .map(replaceConstraintsInstanceSource(oldInstanceName, newInstanceName))
93             .collect(Collectors.toList());
94         propertyFilter.setConstraints(constraints);
95     }
96
97     private static Function<PropertyFilterConstraintDataDefinition, PropertyFilterConstraintDataDefinition> replaceConstraintsInstanceSource(
98         final String oldInstanceName, final String newInstanceName) {
99
100         return constraint -> {
101             final ToscaFunction toscaFunction = new FilterConstraintMapper().parseValueToToscaFunction(constraint.getValue()).orElse(null);
102             if (toscaFunction == null) {
103                 return constraint;
104             }
105             renameToscaFunctionComponentInstance(toscaFunction, oldInstanceName, newInstanceName);
106             return constraint;
107         };
108     }
109
110     private static void renameToscaFunctionComponentInstance(final ToscaFunction toscaFunction, final String oldInstanceName,
111                                                              final String newInstanceName) {
112         switch (toscaFunction.getType()) {
113             case GET_PROPERTY:
114             case GET_ATTRIBUTE: {
115                 final ToscaGetFunctionDataDefinition toscaGetFunctionDataDefinition = (ToscaGetFunctionDataDefinition) toscaFunction;
116                 if (toscaGetFunctionDataDefinition.getSourceName().equals(oldInstanceName)) {
117                     toscaGetFunctionDataDefinition.setSourceName(newInstanceName);
118                 }
119                 break;
120             }
121             case CONCAT: {
122                 final ToscaConcatFunction toscaConcatFunction = (ToscaConcatFunction) toscaFunction;
123                 for (final ToscaFunctionParameter parameter : toscaConcatFunction.getParameters()) {
124                     switch (parameter.getType()) {
125                         case GET_PROPERTY:
126                         case GET_ATTRIBUTE:
127                         case CONCAT:
128                             renameToscaFunctionComponentInstance((ToscaFunction) parameter, oldInstanceName, newInstanceName);
129                             break;
130                         default:
131                     }
132                 }
133                 break;
134             }
135             default:
136         }
137     }
138
139     public static Set<String> getNodesFiltersToBeDeleted(Service service, String ciName) {
140         return service.getComponentInstances().stream().filter(ci -> isNodeFilterUsingChangedCi(ci, ciName)).map(ComponentInstance::getName)
141             .collect(Collectors.toSet());
142     }
143
144     public static Set<String> getNodesFiltersToBeDeleted(Service service, ComponentInstance inCi) {
145         return getNodesFiltersToBeDeleted(service, inCi.getName());
146     }
147
148     private static boolean isNodeFilterUsingChangedCi(ComponentInstance ci, String name) {
149         if (CollectionUtils.isEmpty(ci.getDirectives())) {
150             return false;
151         }
152         if (ci.getNodeFilter() == null || ci.getNodeFilter().getProperties() == null
153             || ci.getNodeFilter().getProperties().getListToscaDataDefinition() == null) {
154             return false;
155         }
156         return ci.getNodeFilter().getProperties().getListToscaDataDefinition().stream()
157             .anyMatch(property -> isPropertyConstraintChangedByCi(property, name));
158     }
159
160     public static boolean isPropertyConstraintChangedByCi(PropertyFilterDataDefinition propertyFilterDataDefinition,
161                                                            String name) {
162         List<PropertyFilterConstraintDataDefinition> constraints = propertyFilterDataDefinition.getConstraints();
163         if (CollectionUtils.isEmpty(constraints)) {
164             return false;
165         }
166         return constraints.stream().anyMatch(constraint -> isConstraintChangedByCi(constraint, name));
167     }
168
169     private static boolean isConstraintChangedByCi(final PropertyFilterConstraintDataDefinition constraint, final String name) {
170         if (constraint.getValueType() == FilterValueType.GET_PROPERTY || constraint.getValueType() == FilterValueType.GET_ATTRIBUTE) {
171             final ToscaFunction toscaFunction = new FilterConstraintMapper().parseValueToToscaFunction(constraint.getValue()).orElse(null);
172             if (toscaFunction != null) {
173                 final ToscaGetFunctionDataDefinition toscaGetFunction = (ToscaGetFunctionDataDefinition) toscaFunction;
174                 return toscaGetFunction.getSourceName().equals(name);
175             }
176         }
177         return false;
178     }
179
180     public static Set<String> getNodesFiltersToBeDeleted(Service service, InputDefinition changedInput) {
181         return service.getComponentInstances().stream().filter(ci -> isNodeFilterUsingChangedInput(ci, changedInput)).map(ComponentInstance::getName)
182             .collect(Collectors.toSet());
183     }
184
185     private static boolean isNodeFilterUsingChangedInput(ComponentInstance ci, InputDefinition changedInput) {
186         if (CollectionUtils.isEmpty(ci.getDirectives())) {
187             return false;
188         }
189         return ci.getNodeFilter().getProperties().getListToscaDataDefinition().stream()
190             .anyMatch(property -> isPropertyConstraintChangedByInput(property, changedInput));
191     }
192
193     private static boolean isPropertyConstraintChangedByInput(final PropertyFilterDataDefinition propertyFilterDataDefinition,
194                                                               final InputDefinition changedInput) {
195         final List<PropertyFilterConstraintDataDefinition> constraints = propertyFilterDataDefinition.getConstraints();
196         return constraints.stream().anyMatch(constraint -> isConstraintChangedByInput(constraint, changedInput));
197     }
198
199     private static boolean isConstraintChangedByInput(final PropertyFilterConstraintDataDefinition constraint, final InputDefinition changedInput) {
200         if (constraint.getValueType() == FilterValueType.GET_INPUT) {
201             final ToscaFunction toscaFunction = new FilterConstraintMapper().parseValueToToscaFunction(constraint.getValue()).orElse(null);
202             if (toscaFunction != null) {
203                 final ToscaGetFunctionDataDefinition toscaGetFunction = (ToscaGetFunctionDataDefinition) toscaFunction;
204                 return toscaGetFunction.getPropertyPathFromSource().contains(changedInput.getName());
205             }
206         }
207         return false;
208     }
209 }