Catalog alignment
[sdc.git] / catalog-model / src / main / java / org / openecomp / sdc / be / model / jsonjanusgraph / utils / CapabilityRequirementNameResolver.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.openecomp.sdc.be.model.jsonjanusgraph.utils;
22
23 import org.apache.commons.collections.CollectionUtils;
24 import org.apache.commons.collections.MapUtils;
25 import org.apache.commons.lang3.StringUtils;
26 import org.openecomp.sdc.be.config.BeEcompErrorManager;
27 import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition;
28 import org.openecomp.sdc.be.datatypes.elements.ComponentInstanceDataDefinition;
29 import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition;
30 import org.openecomp.sdc.be.datatypes.elements.MapCapabilityProperty;
31 import org.openecomp.sdc.be.datatypes.elements.MapListCapabilityDataDefinition;
32 import org.openecomp.sdc.be.datatypes.elements.MapPropertiesDataDefinition;
33 import org.openecomp.sdc.be.datatypes.elements.RequirementDataDefinition;
34 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
35 import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.TopologyTemplate;
36 import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.ToscaElement;
37 import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.ToscaElementTypeEnum;
38 import org.openecomp.sdc.be.model.utils.ComponentUtilities;
39 import org.openecomp.sdc.common.log.wrappers.Logger;
40
41 import java.util.Collections;
42 import java.util.HashMap;
43 import java.util.Iterator;
44 import java.util.List;
45 import java.util.Map;
46 import java.util.Objects;
47 import java.util.Optional;
48 import java.util.function.Function;
49 import java.util.stream.Collectors;
50
51 import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
52 import static org.apache.commons.lang3.StringUtils.isBlank;
53
54 public class CapabilityRequirementNameResolver {
55
56     private static final Logger log = Logger.getLogger(CapabilityRequirementNameResolver.class);
57     private static final String PATH_DELIMITER = ".";
58
59     public static void updateNamesOfCalculatedCapabilitiesRequirements(TopologyTemplate toscaElement, String ownerId, String ownerName, Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
60         Map<String,ToscaElement> componentCacheToRepair = new HashMap<>();
61         log.debug("#updateNamesOfCalculatedCapabilitiesRequirements");
62         updateCalculatedCapabilitiesNames(componentCacheToRepair, toscaElement, ownerId, ownerName, originGetter);
63         updateCalculatedRequirementsNames(componentCacheToRepair, toscaElement, ownerId, ownerName, originGetter);
64         updateCalculatedCapabilitiesPropertiesKeys(toscaElement, ownerId);
65     }
66
67     private static void updateCalculatedCapabilitiesPropertiesKeys(TopologyTemplate toscaElement, String ownerId) {
68         if(calCapPropertiesExist(toscaElement, ownerId)){
69             MapCapabilityProperty newProps =  new MapCapabilityProperty();
70             toscaElement.getCalculatedCapabilitiesProperties().get(ownerId)
71                     .getMapToscaDataDefinition()
72                     .forEach((k, v)-> updateAndAddCalculatedCapabilitiesProperties(k, v, toscaElement.getCalculatedCapabilities().get(ownerId), newProps));
73             if(MapUtils.isNotEmpty(newProps.getMapToscaDataDefinition())) {
74                 toscaElement.getCalculatedCapabilitiesProperties().put(ownerId, newProps);
75             }
76         }
77     }
78
79     private static boolean calCapPropertiesExist(TopologyTemplate toscaElement, String ownerId) {
80         return toscaElement.getCalculatedCapabilitiesProperties() != null
81                 && toscaElement.getCalculatedCapabilitiesProperties().get(ownerId) != null
82                 && MapUtils.isNotEmpty(toscaElement.getCalculatedCapabilitiesProperties().get(ownerId).getMapToscaDataDefinition())
83                 && capabilitiesExist(toscaElement, ownerId);
84     }
85
86     private static void updateCalculatedRequirementsNames(Map<String, ToscaElement> componentCacheToRepair, TopologyTemplate toscaElement, String ownerId, String ownerName, Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
87         if(requirementsExist(toscaElement, ownerId)){
88             String prefix = ownerName + PATH_DELIMITER;
89             repairReqNames(componentCacheToRepair, toscaElement, ownerId, originGetter);
90             toscaElement.getCalculatedRequirements().get(ownerId)
91                     .getMapToscaDataDefinition().values().stream()
92                     .flatMap(l -> l.getListToscaDataDefinition().stream())
93                     .forEach(r -> {
94                         if(isRequiredToRepair(r.getName())){
95                             BeEcompErrorManager.getInstance()
96                                     .logBeComponentMissingError("The empty name of the requirement was found. Id: " + r.getUniqueId() + ", ownerId: " + ownerId + ", ownerName: " + ownerName,
97                                             toscaElement.getComponentType().getValue(), toscaElement.getName());
98                         }
99                         if(ComponentUtilities.isNotUpdatedCapReqName(prefix, r.getName(), r.getPreviousName())) {
100                             if(StringUtils.isNotEmpty(r.getPreviousName())){
101                                 r.setParentName(r.getPreviousName());
102                             }
103                             r.setPreviousName(r.getName());
104                         }
105                         r.setName(prefix + r.getPreviousName());
106                     });
107         }
108     }
109
110     private static boolean requirementsExist(TopologyTemplate toscaElement, String ownerId) {
111         return toscaElement.getCalculatedRequirements() != null
112                 && toscaElement.getCalculatedRequirements().get(ownerId) != null
113                 && MapUtils.isNotEmpty(toscaElement.getCalculatedRequirements().get(ownerId).getMapToscaDataDefinition());
114     }
115
116     private static void updateCalculatedCapabilitiesNames(Map<String, ToscaElement> componentCacheToRepair, TopologyTemplate toscaElement, String ownerId, String ownerName, Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
117         if(capabilitiesExist(toscaElement, ownerId)){
118             String prefix = ownerName + PATH_DELIMITER;
119             repairCapNames(componentCacheToRepair, toscaElement, ownerId, originGetter);
120             toscaElement.getCalculatedCapabilities().get(ownerId)
121                     .getMapToscaDataDefinition().values().stream()
122                     .flatMap(l -> l.getListToscaDataDefinition().stream())
123                     .forEach(c -> {
124                         if(isRequiredToRepair(c.getName())){
125                             BeEcompErrorManager.getInstance()
126                                     .logBeComponentMissingError("The empty name of the capability was found. Id: " + c.getUniqueId() + ", ownerId: " + ownerId + ", ownerName: " + ownerName,
127                                             toscaElement.getComponentType().getValue(), toscaElement.getName());
128                         }
129                         if(ComponentUtilities.isNotUpdatedCapReqName(prefix, c.getName(), c.getPreviousName())) {
130                             if(StringUtils.isNotEmpty(c.getPreviousName())){
131                                 c.setParentName(c.getPreviousName());
132                             }
133                             c.setPreviousName(c.getName());
134                         }
135                         c.setName(prefix + c.getPreviousName());
136                     });
137         }
138     }
139
140     private static boolean capabilitiesExist(TopologyTemplate toscaElement, String ownerId) {
141         return toscaElement.getCalculatedCapabilities() != null
142                 && toscaElement.getCalculatedCapabilities().get(ownerId) != null
143                 && MapUtils.isNotEmpty(toscaElement.getCalculatedCapabilities().get(ownerId).getMapToscaDataDefinition());
144     }
145
146     private static void repairCapNames(Map<String, ToscaElement> componentCacheToRepair, TopologyTemplate toscaElement, String ownerId, Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
147         log.debug("#repairCapNames");
148         boolean emptyNameFound = toscaElement.getCalculatedCapabilities() != null
149                 && toscaElement.getCalculatedCapabilities().get(ownerId) != null
150                 && toscaElement.getCalculatedCapabilities().get(ownerId).getMapToscaDataDefinition() != null
151                 && toscaElement.getCalculatedCapabilities().get(ownerId).getMapToscaDataDefinition().values()
152                 .stream()
153                 .filter(Objects::nonNull)
154                 .flatMap(l -> l.getListToscaDataDefinition().stream())
155                 .filter(Objects::nonNull)
156                 .anyMatch(c -> isRequiredToRepair(c.getName()));
157
158         ComponentInstanceDataDefinition instance = toscaElement.getComponentInstances() != null ?
159                 toscaElement.getComponentInstances().get(ownerId) : null;
160         if(instance != null && emptyNameFound){
161             log.debug("#repairCapNames - Going to repair the name of the capability for the owner {}. ", ownerId);
162             toscaElement.getCalculatedCapabilities().get(ownerId)
163                     .getMapToscaDataDefinition().values()
164                     .stream()
165                     .flatMap(l -> l.getListToscaDataDefinition().stream())
166                     .forEach(c-> repairCapName(componentCacheToRepair, instance, c, originGetter));
167         }
168     }
169
170     private static void repairReqNames(Map<String, ToscaElement> componentCacheToRepair, TopologyTemplate toscaElement, String ownerId, Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
171         log.debug("#repairReqNames");
172         boolean emptyNameFound = toscaElement.getCalculatedRequirements() != null
173                 && toscaElement.getCalculatedRequirements().get(ownerId) != null
174                 && toscaElement.getCalculatedRequirements().get(ownerId).getMapToscaDataDefinition() != null
175                 && toscaElement.getCalculatedRequirements().get(ownerId).getMapToscaDataDefinition().values()
176                 .stream()
177                 .filter(Objects::nonNull)
178                 .flatMap(l -> l.getListToscaDataDefinition().stream())
179                 .filter(Objects::nonNull)
180                 .anyMatch(r -> isRequiredToRepair(r.getName()));
181
182         ComponentInstanceDataDefinition instance = toscaElement.getComponentInstances() != null ?
183                 toscaElement.getComponentInstances().get(ownerId) : null;
184         if(instance != null && emptyNameFound){
185             log.debug("#repairReqNames - Going to repair the name of the requirement for the owner {}. ", ownerId);
186             toscaElement.getCalculatedRequirements().get(ownerId)
187                     .getMapToscaDataDefinition().values()
188                     .stream()
189                     .flatMap(l -> l.getListToscaDataDefinition().stream())
190                     .forEach(r-> repairReqName(componentCacheToRepair, instance, r, originGetter));
191         }
192     }
193
194     private static void repairCapName(Map<String, ToscaElement> componentCacheToRepair, ComponentInstanceDataDefinition instance, CapabilityDataDefinition capability, Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
195         if(isRequiredToRepair(capability.getName())){
196             log.debug("#repairTopologyTemplateCapName - Going to build the name for the capability: ", capability.getUniqueId());
197             buildSetCapName(componentCacheToRepair, capability, instance, originGetter);
198         }
199     }
200
201     private static boolean isRequiredToRepair(String name) {
202         boolean isRequiredToRepair = StringUtils.isEmpty(name) || name.endsWith(".null") || name.contains(".null.");
203         if(isRequiredToRepair){
204             log.debug("#isRequiredToRepair - The name {} should be repaired. ", name) ;
205         } else{
206             log.debug("#isRequiredToRepair - The name {} should not be repaired. ", name) ;
207         }
208         return isRequiredToRepair;
209     }
210
211     private static void repairReqName(Map<String, ToscaElement> componentCacheToRepair, ComponentInstanceDataDefinition instance, RequirementDataDefinition requirement, Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
212         if(isRequiredToRepair(requirement.getName())){
213             log.debug("#repairTopologyTemplateCapName - Going to build the name for the requirement: ", requirement.getUniqueId());
214             buildSetReqName(componentCacheToRepair, requirement, instance, originGetter);
215         }
216     }
217
218     private static void updateAndAddCalculatedCapabilitiesProperties(String stringKey, MapPropertiesDataDefinition properties, MapListCapabilityDataDefinition calculatedCapabilities, MapCapabilityProperty newProps) {
219         String[] key = stringKey.split(ModelConverter.CAP_PROP_DELIM);
220         String capType = key[key.length - 2];
221         String capName = key[key.length - 1];
222         Optional<CapabilityDataDefinition> foundCapOpt = calculatedCapabilities.getMapToscaDataDefinition().get(capType)
223                 .getListToscaDataDefinition().stream()
224                 .filter(c -> StringUtils.isNotEmpty(c.getPreviousName())&& c.getPreviousName().equals(capName))
225                 .findFirst();
226         foundCapOpt.ifPresent(capabilityDataDefinition -> key[key.length - 1] = capabilityDataDefinition.getName());
227         newProps.put(buildCaLCapPropKey(key),properties);
228     }
229
230     public static void revertNamesOfCalculatedCapabilitiesRequirements(TopologyTemplate toscaElement, String ownerId, Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
231         Map<String,ToscaElement> componentCacheToRepair = new HashMap<>();
232         log.debug("#revertNamesOfCalculatedCapabilitiesRequirements");
233         revertCalculatedCapabilitiesPropertiesKeys(componentCacheToRepair, toscaElement, ownerId, originGetter);
234         revertCalculatedCapabilitiesNames(toscaElement, ownerId);
235         revertCalculatedRequirementsNames(componentCacheToRepair, toscaElement, ownerId, originGetter);
236     }
237
238     private static void revertCalculatedCapabilitiesPropertiesKeys(Map<String, ToscaElement> componentCacheToRepair, TopologyTemplate toscaElement, String ownerId, Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
239         repairCapNames(componentCacheToRepair, toscaElement, ownerId, originGetter);
240         if(calCapPropertiesExist(toscaElement, ownerId)){
241             MapCapabilityProperty newProps =  new MapCapabilityProperty();
242             toscaElement.getCalculatedCapabilitiesProperties().get(ownerId)
243                     .getMapToscaDataDefinition()
244                     .forEach((k,v) -> revertAndAddCalculatedCapabilitiesProperties(k, v, toscaElement.getCalculatedCapabilities().get(ownerId), newProps));
245             if(MapUtils.isNotEmpty(newProps.getMapToscaDataDefinition())) {
246                 toscaElement.getCalculatedCapabilitiesProperties().put(ownerId, newProps);
247             }
248         }
249     }
250
251     private static void revertCalculatedRequirementsNames(Map<String, ToscaElement> componentCacheToRepair, TopologyTemplate toscaElement, String ownerId, Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
252         repairReqNames(componentCacheToRepair, toscaElement, ownerId, originGetter);
253         if(requirementsExist(toscaElement, ownerId)){
254             toscaElement.getCalculatedRequirements().get(ownerId)
255                     .getMapToscaDataDefinition().values().stream()
256                     .flatMap(l -> l.getListToscaDataDefinition().stream())
257                     .forEach(CapabilityRequirementNameResolver::revertReqNames);
258         }
259     }
260
261     private static void revertReqNames(RequirementDataDefinition requirement) {
262         if(StringUtils.isNotEmpty(requirement.getPreviousName())) {
263             requirement.setName(requirement.getPreviousName());
264             requirement.setPreviousName(requirement.getParentName());
265         }
266     }
267
268     private static void revertCalculatedCapabilitiesNames(TopologyTemplate toscaElement, String ownerId) {
269         if(capabilitiesExist(toscaElement, ownerId)){
270             toscaElement.getCalculatedCapabilities().get(ownerId)
271                     .getMapToscaDataDefinition().values().stream()
272                     .flatMap(l -> l.getListToscaDataDefinition().stream())
273                     .forEach(CapabilityRequirementNameResolver::revertCapNames);
274         }
275     }
276
277     private static void revertCapNames(CapabilityDataDefinition capability) {
278         if(StringUtils.isNotEmpty(capability.getPreviousName())) {
279             capability.setName(capability.getPreviousName());
280             capability.setPreviousName(capability.getParentName());
281         }
282     }
283
284     private static void revertAndAddCalculatedCapabilitiesProperties(String stringKey, MapPropertiesDataDefinition properties, MapListCapabilityDataDefinition calculatedCapabilities, MapCapabilityProperty newProps) {
285         String[] key = stringKey.split(ModelConverter.CAP_PROP_DELIM);
286         String capType = key[key.length - 2];
287         String capName = key[key.length - 1];
288         Optional<CapabilityDataDefinition> foundCapOpt = calculatedCapabilities.getMapToscaDataDefinition().get(capType)
289                 .getListToscaDataDefinition().stream()
290                 .filter(c -> c.getName().equals(capName) && StringUtils.isNotEmpty(c.getPreviousName()))
291                 .findFirst();
292         foundCapOpt.ifPresent(capabilityDataDefinition -> key[key.length - 1] = capabilityDataDefinition.getPreviousName());
293         newProps.put(buildCaLCapPropKey(key), properties);
294     }
295
296     private static String buildCaLCapPropKey(String[] keyArray) {
297         StringBuilder key = new StringBuilder();
298         for(int i = 0; i< keyArray.length; ++i){
299             key.append(keyArray[i]);
300             if(i < keyArray.length - 1){
301                 key.append(ModelConverter.CAP_PROP_DELIM);
302             }
303         }
304         return key.toString();
305     }
306
307     private static void buildSetCapName(Map<String, ToscaElement> componentsCache, CapabilityDataDefinition capability, ComponentInstanceDataDefinition instance, Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
308         List<String> reducedPath = capability.getOwnerId() !=null ? getReducedPathByOwner(capability.getPath() , capability.getOwnerId() ) : getReducedPath(capability.getPath()) ;
309         log.debug("reducedPath for ownerId {}, reducedPath {} ", capability.getOwnerId(), reducedPath);
310         reducedPath.remove(reducedPath.size() - 1);
311         ToscaElement originComponent = getOriginComponent(componentsCache, instance, originGetter);
312         String name =  isRequiredToRepair(capability.getParentName()) ?
313                 extractNameFromUniqueId(capability.getUniqueId()) : capability.getParentName();
314         StringBuilder repairedName = buildSubstitutedName(componentsCache, originComponent, reducedPath, originGetter);
315         log.debug("#buildSetCapName - The name for the capability was built: {}", repairedName);
316
317         capability.setName(repairedName.append(name).toString());
318         if(isRequiredToRepair(capability.getPreviousName())){
319             capability.setPreviousName(capability.getName().substring(capability.getName().indexOf(PATH_DELIMITER) + 1));
320         }
321         if(isRequiredToRepair(capability.getParentName())){
322             capability.setParentName(name);
323         }
324     }
325
326     private static void buildSetReqName(Map<String, ToscaElement> componentsCache, RequirementDataDefinition requirement, ComponentInstanceDataDefinition instance, Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
327         List<String> reducedPath = requirement.getOwnerId() !=null ? getReducedPathByOwner(requirement.getPath() , requirement.getOwnerId() ) : getReducedPath(requirement.getPath()) ;
328         log.debug("reducedPath for ownerId {}, reducedPath {} ", requirement.getOwnerId(), reducedPath);
329         reducedPath.remove(reducedPath.size() - 1);
330         ToscaElement originComponent = getOriginComponent(componentsCache, instance, originGetter);
331         String name =  isRequiredToRepair(requirement.getParentName()) ?
332                 extractNameFromUniqueId(requirement.getUniqueId()) : requirement.getParentName();
333
334         StringBuilder repairedName = buildSubstitutedName(componentsCache, originComponent, reducedPath, originGetter);
335         log.debug("#buildSetReqName - The name for the capability was built: ", repairedName);
336         requirement.setName(repairedName.append(name).toString());
337         if(isRequiredToRepair(requirement.getPreviousName())){
338             requirement.setPreviousName(requirement.getName().substring(requirement.getName().indexOf(PATH_DELIMITER) + 1));
339         }
340         if(isRequiredToRepair(requirement.getParentName())){
341             requirement.setParentName(name);
342         }
343     }
344
345     private static String extractNameFromUniqueId(String uniqueId) {
346         String[] uid = uniqueId.split("\\.");
347         return uid [uid.length - 1];
348     }
349
350     private static StringBuilder buildSubstitutedName(Map<String, ToscaElement> componentsCache, ToscaElement originComponent, List<String> path, Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
351         StringBuilder substitutedName = new StringBuilder();
352         log.debug("#buildSubstitutedName");
353         if(isNotEmpty(path) && isTopologyTemplateNotCvfc(originComponent)){
354             log.debug("#buildSubstitutedName");
355             List<String> reducedPath = getReducedPath(path);
356             Collections.reverse(reducedPath);
357             appendNameRecursively(componentsCache, originComponent, reducedPath.iterator(), substitutedName, originGetter);
358         }
359         return substitutedName;
360     }
361
362     private static boolean isTopologyTemplateNotCvfc(ToscaElement originComponent) {
363         return originComponent.getToscaType() == ToscaElementTypeEnum.TOPOLOGY_TEMPLATE && originComponent.getResourceType() != ResourceTypeEnum.CVFC;
364     }
365
366     private static ToscaElement getOriginComponent(Map<String, ToscaElement> componentsCache, ComponentInstanceDataDefinition instance, Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
367         if(componentsCache.containsKey(getActualComponentUid(instance))){
368             return componentsCache.get(getActualComponentUid(instance));
369         }
370         ToscaElement origin = originGetter.apply(instance);
371         componentsCache.put(origin.getUniqueId(), origin);
372         return origin;
373     }
374
375     public static String getActualComponentUid(ComponentInstanceDataDefinition instance) {
376         return instance.getIsProxy() ? instance.getSourceModelUid() : instance.getComponentUid();
377     }
378
379     private static List<String> getReducedPath(List<String> path) {
380         return path.stream().distinct().collect(Collectors.toList());
381     }
382
383     private static void appendNameRecursively(Map<String, ToscaElement> componentsCache, ToscaElement originComponent, Iterator<String> instanceIdIter, StringBuilder substitutedName, Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
384         log.debug("#appendNameRecursively");
385         if(isTopologyTemplateNotCvfc(originComponent)
386                 && MapUtils.isNotEmpty(((TopologyTemplate)originComponent).getComponentInstances()) && instanceIdIter.hasNext()){
387
388             String ownerId = instanceIdIter.next();
389             Optional<ComponentInstanceDataDefinition> instanceOpt = ((TopologyTemplate)originComponent).getComponentInstances().values().stream().filter(i -> i.getUniqueId().equals(ownerId)).findFirst();
390             if(instanceOpt.isPresent()){
391                 substitutedName.append(instanceOpt.get().getNormalizedName()).append(PATH_DELIMITER);
392                 ToscaElement getOriginRes = getOriginComponent(componentsCache, instanceOpt.get(), originGetter);
393                 appendNameRecursively(componentsCache, getOriginRes, instanceIdIter, substitutedName, originGetter);
394             } else if(MapUtils.isNotEmpty(((TopologyTemplate)originComponent).getGroups())){
395                 Optional<GroupDataDefinition> groupOpt = ((TopologyTemplate)originComponent).getGroups().values().stream().filter(g -> g.getUniqueId().equals(ownerId)).findFirst();
396                 groupOpt.ifPresent(groupDataDefinition -> substitutedName.append(groupDataDefinition.getName()).append(PATH_DELIMITER));
397             } else {
398                 log.debug("Failed to find an capability owner with uniqueId {} on a component with uniqueId {}", ownerId, originComponent.getUniqueId());
399             }
400         }
401     }
402
403     private static List<String> getReducedPathByOwner(List<String> path , String ownerId) {
404         log.debug("ownerId {}, path {} ", ownerId, path);
405         if ( CollectionUtils.isEmpty(path) ){
406             log.debug("cannot perform reduce by owner, path to component is empty");
407             return path;
408         }
409         if ( isBlank(ownerId) ){
410             log.debug("cannot perform reduce by owner, component owner is empty");
411             return path;
412         }
413         //reduce by owner
414         Map map = path.stream().collect( Collectors.toMap( it -> dropLast(it, PATH_DELIMITER) , Function.identity() , (a , b ) ->  a.endsWith(ownerId) ? a : b ));
415         //reduce list&duplicates and preserve order
416         return path.stream().distinct().filter(it -> map.values().contains(it) ).collect(Collectors.toList());
417     }
418     private static String dropLast( String path, String delimiter ) {
419         if (isBlank(path) || isBlank(delimiter)){
420             return path;
421         }
422         return path.substring(0, path.lastIndexOf(delimiter));
423     }
424 }