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