1 package org.openecomp.sdc.be.model.jsonjanusgraph.utils;
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;
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;
20 public class CapabilityRequirementNameResolver {
22 private static final Logger log = Logger.getLogger(CapabilityRequirementNameResolver.class);
23 private static final String PATH_DELIMITER = ".";
25 private CapabilityRequirementNameResolver() {
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);
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);
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);
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())
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());
68 if (ComponentUtilities.isNotUpdatedCapReqName(prefix, r.getName(), r.getPreviousName())) {
69 if (StringUtils.isNotEmpty(r.getPreviousName())) {
70 r.setParentName(r.getPreviousName());
72 r.setPreviousName(r.getName());
74 r.setName(prefix + r.getPreviousName());
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());
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())
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());
98 if (ComponentUtilities.isNotUpdatedCapReqName(prefix, c.getName(), c.getPreviousName())) {
99 if (StringUtils.isNotEmpty(c.getPreviousName())) {
100 c.setParentName(c.getPreviousName());
102 c.setPreviousName(c.getName());
104 c.setName(prefix + c.getPreviousName());
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());
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()
122 .filter(Objects::nonNull)
123 .flatMap(l -> l.getListToscaDataDefinition().stream())
124 .filter(Objects::nonNull)
125 .anyMatch(c -> isRequiredToRepair(c.getName()));
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()
134 .flatMap(l -> l.getListToscaDataDefinition().stream())
135 .forEach(c -> repairCapName(componentCacheToRepair, instance, c, originGetter));
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()
146 .filter(Objects::nonNull)
147 .flatMap(l -> l.getListToscaDataDefinition().stream())
148 .filter(Objects::nonNull)
149 .anyMatch(r -> isRequiredToRepair(r.getName()));
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()
158 .flatMap(l -> l.getListToscaDataDefinition().stream())
159 .forEach(r -> repairReqName(componentCacheToRepair, instance, r, originGetter));
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);
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);
175 log.debug("#isRequiredToRepair - The name {} should not be repaired. ", name);
177 return isRequiredToRepair;
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);
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))
195 foundCapOpt.ifPresent(capabilityDataDefinition -> key[key.length - 1] = capabilityDataDefinition.getName());
196 newProps.put(buildCaLCapPropKey(key), properties);
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);
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);
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);
230 private static void revertReqNames(RequirementDataDefinition requirement) {
231 if (StringUtils.isNotEmpty(requirement.getPreviousName())) {
232 requirement.setName(requirement.getPreviousName());
233 requirement.setPreviousName(requirement.getParentName());
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);
246 private static void revertCapNames(CapabilityDataDefinition capability) {
247 if (StringUtils.isNotEmpty(capability.getPreviousName())) {
248 capability.setName(capability.getPreviousName());
249 capability.setPreviousName(capability.getParentName());
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()))
261 foundCapOpt.ifPresent(capabilityDataDefinition -> key[key.length - 1] = capabilityDataDefinition.getPreviousName());
262 newProps.put(buildCaLCapPropKey(key), properties);
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);
273 return key.toString();
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);
286 capability.setName(repairedName.append(name).toString());
287 if (isRequiredToRepair(capability.getPreviousName())) {
288 capability.setPreviousName(capability.getName().substring(capability.getName().indexOf(PATH_DELIMITER) + 1));
290 if (isRequiredToRepair(capability.getParentName())) {
291 capability.setParentName(name);
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();
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));
309 if (isRequiredToRepair(requirement.getParentName())) {
310 requirement.setParentName(name);
314 private static String extractNameFromUniqueId(String uniqueId) {
315 String[] uid = uniqueId.split("\\.");
316 return uid[uid.length - 1];
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);
328 return substitutedName;
331 private static boolean isTopologyTemplateNotCvfc(ToscaElement originComponent) {
332 return originComponent.getToscaType() == ToscaElementTypeEnum.TOPOLOGY_TEMPLATE && originComponent.getResourceType() != ResourceTypeEnum.CVFC;
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));
339 ToscaElement origin = originGetter.apply(instance);
340 componentsCache.put(origin.getUniqueId(), origin);
344 public static String getActualComponentUid(ComponentInstanceDataDefinition instance) {
345 return instance.getIsProxy() ? instance.getSourceModelUid() : instance.getComponentUid();
348 private static List<String> getReducedPath(List<String> path) {
349 return path.stream().distinct().collect(Collectors.toList());
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()) {
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));
367 log.debug("Failed to find an capability owner with uniqueId {} on a component with uniqueId {}", ownerId, originComponent.getUniqueId());
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");
378 if (isBlank(ownerId)) {
379 log.debug("cannot perform reduce by owner, component owner is empty");
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());
388 private static String dropLast(String path, String delimiter) {
389 if (isBlank(path) || isBlank(delimiter)) {
392 return path.substring(0, path.lastIndexOf(delimiter));