2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
20 package org.openecomp.sdc.be.model.jsonjanusgraph.utils;
22 import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
23 import static org.apache.commons.lang3.StringUtils.isBlank;
25 import java.util.Collections;
26 import java.util.HashMap;
27 import java.util.Iterator;
28 import java.util.List;
30 import java.util.Objects;
31 import java.util.Optional;
32 import java.util.function.Function;
33 import java.util.stream.Collectors;
34 import org.apache.commons.collections.CollectionUtils;
35 import org.apache.commons.collections.MapUtils;
36 import org.apache.commons.lang3.StringUtils;
37 import org.openecomp.sdc.be.config.BeEcompErrorManager;
38 import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition;
39 import org.openecomp.sdc.be.datatypes.elements.ComponentInstanceDataDefinition;
40 import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition;
41 import org.openecomp.sdc.be.datatypes.elements.MapCapabilityProperty;
42 import org.openecomp.sdc.be.datatypes.elements.MapListCapabilityDataDefinition;
43 import org.openecomp.sdc.be.datatypes.elements.MapPropertiesDataDefinition;
44 import org.openecomp.sdc.be.datatypes.elements.RequirementDataDefinition;
45 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
46 import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.TopologyTemplate;
47 import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.ToscaElement;
48 import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.ToscaElementTypeEnum;
49 import org.openecomp.sdc.be.model.utils.ComponentUtilities;
50 import org.openecomp.sdc.common.log.wrappers.Logger;
52 public class CapabilityRequirementNameResolver {
54 private static final Logger log = Logger.getLogger(CapabilityRequirementNameResolver.class);
55 private static final String PATH_DELIMITER = ".";
57 public static void updateNamesOfCalculatedCapabilitiesRequirements(TopologyTemplate toscaElement, String ownerId, String ownerName,
58 Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
59 Map<String, ToscaElement> componentCacheToRepair = new HashMap<>();
60 log.debug("#updateNamesOfCalculatedCapabilitiesRequirements");
61 updateCalculatedCapabilitiesNames(componentCacheToRepair, toscaElement, ownerId, ownerName, originGetter);
62 updateCalculatedRequirementsNames(componentCacheToRepair, toscaElement, ownerId, ownerName, originGetter);
63 updateCalculatedCapabilitiesPropertiesKeys(toscaElement, ownerId);
66 private static void updateCalculatedCapabilitiesPropertiesKeys(TopologyTemplate toscaElement, String ownerId) {
67 if (calCapPropertiesExist(toscaElement, ownerId)) {
68 MapCapabilityProperty newProps = new MapCapabilityProperty();
69 toscaElement.getCalculatedCapabilitiesProperties().get(ownerId).getMapToscaDataDefinition().forEach(
70 (k, v) -> updateAndAddCalculatedCapabilitiesProperties(k, v, toscaElement.getCalculatedCapabilities().get(ownerId), newProps));
71 if (MapUtils.isNotEmpty(newProps.getMapToscaDataDefinition())) {
72 toscaElement.getCalculatedCapabilitiesProperties().put(ownerId, newProps);
77 private static boolean calCapPropertiesExist(TopologyTemplate toscaElement, String ownerId) {
78 return toscaElement.getCalculatedCapabilitiesProperties() != null && toscaElement.getCalculatedCapabilitiesProperties().get(ownerId) != null
79 && MapUtils.isNotEmpty(toscaElement.getCalculatedCapabilitiesProperties().get(ownerId).getMapToscaDataDefinition()) && capabilitiesExist(
80 toscaElement, ownerId);
83 private static void updateCalculatedRequirementsNames(Map<String, ToscaElement> componentCacheToRepair, TopologyTemplate toscaElement,
84 String ownerId, String ownerName,
85 Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
86 if (requirementsExist(toscaElement, ownerId)) {
87 String prefix = ownerName + PATH_DELIMITER;
88 repairReqNames(componentCacheToRepair, toscaElement, ownerId, originGetter);
89 toscaElement.getCalculatedRequirements().get(ownerId).getMapToscaDataDefinition().values().stream()
90 .flatMap(l -> l.getListToscaDataDefinition().stream()).forEach(r -> {
91 if (isRequiredToRepair(r.getName())) {
92 BeEcompErrorManager.getInstance().logBeComponentMissingError(
93 "The empty name of the requirement was found. Id: " + r.getUniqueId() + ", ownerId: " + ownerId + ", ownerName: " + ownerName,
94 toscaElement.getComponentType().getValue(), toscaElement.getName());
96 if (ComponentUtilities.isNotUpdatedCapReqName(prefix, r.getName(), r.getPreviousName())) {
97 if (StringUtils.isNotEmpty(r.getPreviousName())) {
98 r.setParentName(r.getPreviousName());
100 r.setPreviousName(r.getName());
102 r.setName(prefix + r.getPreviousName());
107 private static boolean requirementsExist(TopologyTemplate toscaElement, String ownerId) {
108 return toscaElement.getCalculatedRequirements() != null && toscaElement.getCalculatedRequirements().get(ownerId) != null && MapUtils
109 .isNotEmpty(toscaElement.getCalculatedRequirements().get(ownerId).getMapToscaDataDefinition());
112 private static void updateCalculatedCapabilitiesNames(Map<String, ToscaElement> componentCacheToRepair, TopologyTemplate toscaElement,
113 String ownerId, String ownerName,
114 Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
115 if (capabilitiesExist(toscaElement, ownerId)) {
116 String prefix = ownerName + PATH_DELIMITER;
117 repairCapNames(componentCacheToRepair, toscaElement, ownerId, originGetter);
118 toscaElement.getCalculatedCapabilities().get(ownerId).getMapToscaDataDefinition().values().stream()
119 .flatMap(l -> l.getListToscaDataDefinition().stream()).forEach(c -> {
120 if (isRequiredToRepair(c.getName())) {
121 BeEcompErrorManager.getInstance().logBeComponentMissingError(
122 "The empty name of the capability was found. Id: " + c.getUniqueId() + ", ownerId: " + ownerId + ", ownerName: " + ownerName,
123 toscaElement.getComponentType().getValue(), toscaElement.getName());
125 if (ComponentUtilities.isNotUpdatedCapReqName(prefix, c.getName(), c.getPreviousName())) {
126 if (StringUtils.isNotEmpty(c.getPreviousName())) {
127 c.setParentName(c.getPreviousName());
129 c.setPreviousName(c.getName());
131 c.setName(prefix + c.getPreviousName());
136 private static boolean capabilitiesExist(TopologyTemplate toscaElement, String ownerId) {
137 return toscaElement.getCalculatedCapabilities() != null && toscaElement.getCalculatedCapabilities().get(ownerId) != null && MapUtils
138 .isNotEmpty(toscaElement.getCalculatedCapabilities().get(ownerId).getMapToscaDataDefinition());
141 private static void repairCapNames(Map<String, ToscaElement> componentCacheToRepair, TopologyTemplate toscaElement, String ownerId,
142 Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
143 log.debug("#repairCapNames");
144 boolean emptyNameFound = toscaElement.getCalculatedCapabilities() != null && toscaElement.getCalculatedCapabilities().get(ownerId) != null
145 && toscaElement.getCalculatedCapabilities().get(ownerId).getMapToscaDataDefinition() != null && toscaElement.getCalculatedCapabilities()
146 .get(ownerId).getMapToscaDataDefinition().values().stream().filter(Objects::nonNull).flatMap(l -> l.getListToscaDataDefinition().stream())
147 .filter(Objects::nonNull).anyMatch(c -> isRequiredToRepair(c.getName()));
148 ComponentInstanceDataDefinition instance =
149 toscaElement.getComponentInstances() != null ? toscaElement.getComponentInstances().get(ownerId) : null;
150 if (instance != null && emptyNameFound) {
151 log.debug("#repairCapNames - Going to repair the name of the capability for the owner {}. ", ownerId);
152 toscaElement.getCalculatedCapabilities().get(ownerId).getMapToscaDataDefinition().values().stream()
153 .flatMap(l -> l.getListToscaDataDefinition().stream()).forEach(c -> repairCapName(componentCacheToRepair, instance, c, originGetter));
157 private static void repairReqNames(Map<String, ToscaElement> componentCacheToRepair, TopologyTemplate toscaElement, String ownerId,
158 Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
159 log.debug("#repairReqNames");
160 boolean emptyNameFound = toscaElement.getCalculatedRequirements() != null && toscaElement.getCalculatedRequirements().get(ownerId) != null
161 && toscaElement.getCalculatedRequirements().get(ownerId).getMapToscaDataDefinition() != null && toscaElement.getCalculatedRequirements()
162 .get(ownerId).getMapToscaDataDefinition().values().stream().filter(Objects::nonNull).flatMap(l -> l.getListToscaDataDefinition().stream())
163 .filter(Objects::nonNull).anyMatch(r -> isRequiredToRepair(r.getName()));
164 ComponentInstanceDataDefinition instance =
165 toscaElement.getComponentInstances() != null ? toscaElement.getComponentInstances().get(ownerId) : null;
166 if (instance != null && emptyNameFound) {
167 log.debug("#repairReqNames - Going to repair the name of the requirement for the owner {}. ", ownerId);
168 toscaElement.getCalculatedRequirements().get(ownerId).getMapToscaDataDefinition().values().stream()
169 .flatMap(l -> l.getListToscaDataDefinition().stream()).forEach(r -> repairReqName(componentCacheToRepair, instance, r, originGetter));
173 private static void repairCapName(Map<String, ToscaElement> componentCacheToRepair, ComponentInstanceDataDefinition instance,
174 CapabilityDataDefinition capability, Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
175 if (isRequiredToRepair(capability.getName())) {
176 log.debug("#repairTopologyTemplateCapName - Going to build the name for the capability: ", capability.getUniqueId());
177 buildSetCapName(componentCacheToRepair, capability, instance, originGetter);
181 private static boolean isRequiredToRepair(String name) {
182 boolean isRequiredToRepair = StringUtils.isEmpty(name) || name.endsWith(".null") || name.contains(".null.");
183 if (isRequiredToRepair) {
184 log.debug("#isRequiredToRepair - The name {} should be repaired. ", name);
186 log.debug("#isRequiredToRepair - The name {} should not be repaired. ", name);
188 return isRequiredToRepair;
191 private static void repairReqName(Map<String, ToscaElement> componentCacheToRepair, ComponentInstanceDataDefinition instance,
192 RequirementDataDefinition requirement, Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
193 if (isRequiredToRepair(requirement.getName())) {
194 log.debug("#repairTopologyTemplateCapName - Going to build the name for the requirement: ", requirement.getUniqueId());
195 buildSetReqName(componentCacheToRepair, requirement, instance, originGetter);
199 private static void updateAndAddCalculatedCapabilitiesProperties(String stringKey, MapPropertiesDataDefinition properties,
200 MapListCapabilityDataDefinition calculatedCapabilities,
201 MapCapabilityProperty newProps) {
202 String[] key = stringKey.split(ModelConverter.CAP_PROP_DELIM);
203 String capType = key[key.length - 2];
204 String capName = key[key.length - 1];
205 Optional<CapabilityDataDefinition> foundCapOpt = calculatedCapabilities.getMapToscaDataDefinition().get(capType).getListToscaDataDefinition()
206 .stream().filter(c -> StringUtils.isNotEmpty(c.getPreviousName()) && c.getPreviousName().equals(capName)).findFirst();
207 foundCapOpt.ifPresent(capabilityDataDefinition -> key[key.length - 1] = capabilityDataDefinition.getName());
208 newProps.put(buildCaLCapPropKey(key), properties);
211 public static void revertNamesOfCalculatedCapabilitiesRequirements(TopologyTemplate toscaElement, String ownerId,
212 Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
213 Map<String, ToscaElement> componentCacheToRepair = new HashMap<>();
214 log.debug("#revertNamesOfCalculatedCapabilitiesRequirements");
215 revertCalculatedCapabilitiesPropertiesKeys(componentCacheToRepair, toscaElement, ownerId, originGetter);
216 revertCalculatedCapabilitiesNames(toscaElement, ownerId);
217 revertCalculatedRequirementsNames(componentCacheToRepair, toscaElement, ownerId, originGetter);
220 private static void revertCalculatedCapabilitiesPropertiesKeys(Map<String, ToscaElement> componentCacheToRepair, TopologyTemplate toscaElement,
222 Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
223 repairCapNames(componentCacheToRepair, toscaElement, ownerId, originGetter);
224 if (calCapPropertiesExist(toscaElement, ownerId)) {
225 MapCapabilityProperty newProps = new MapCapabilityProperty();
226 toscaElement.getCalculatedCapabilitiesProperties().get(ownerId).getMapToscaDataDefinition().forEach(
227 (k, v) -> revertAndAddCalculatedCapabilitiesProperties(k, v, toscaElement.getCalculatedCapabilities().get(ownerId), newProps));
228 if (MapUtils.isNotEmpty(newProps.getMapToscaDataDefinition())) {
229 toscaElement.getCalculatedCapabilitiesProperties().put(ownerId, newProps);
234 private static void revertCalculatedRequirementsNames(Map<String, ToscaElement> componentCacheToRepair, TopologyTemplate toscaElement,
235 String ownerId, Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
236 repairReqNames(componentCacheToRepair, toscaElement, ownerId, originGetter);
237 if (requirementsExist(toscaElement, ownerId)) {
238 toscaElement.getCalculatedRequirements().get(ownerId).getMapToscaDataDefinition().values().stream()
239 .flatMap(l -> l.getListToscaDataDefinition().stream()).forEach(CapabilityRequirementNameResolver::revertReqNames);
243 private static void revertReqNames(RequirementDataDefinition requirement) {
244 if (StringUtils.isNotEmpty(requirement.getPreviousName())) {
245 requirement.setName(requirement.getPreviousName());
246 requirement.setPreviousName(requirement.getParentName());
250 private static void revertCalculatedCapabilitiesNames(TopologyTemplate toscaElement, String ownerId) {
251 if (capabilitiesExist(toscaElement, ownerId)) {
252 toscaElement.getCalculatedCapabilities().get(ownerId).getMapToscaDataDefinition().values().stream()
253 .flatMap(l -> l.getListToscaDataDefinition().stream()).forEach(CapabilityRequirementNameResolver::revertCapNames);
257 private static void revertCapNames(CapabilityDataDefinition capability) {
258 if (StringUtils.isNotEmpty(capability.getPreviousName())) {
259 capability.setName(capability.getPreviousName());
260 capability.setPreviousName(capability.getParentName());
264 private static void revertAndAddCalculatedCapabilitiesProperties(String stringKey, MapPropertiesDataDefinition properties,
265 MapListCapabilityDataDefinition calculatedCapabilities,
266 MapCapabilityProperty newProps) {
267 String[] key = stringKey.split(ModelConverter.CAP_PROP_DELIM);
268 String capType = key[key.length - 2];
269 String capName = key[key.length - 1];
270 Optional<CapabilityDataDefinition> foundCapOpt = calculatedCapabilities.getMapToscaDataDefinition().get(capType).getListToscaDataDefinition()
271 .stream().filter(c -> c.getName().equals(capName) && StringUtils.isNotEmpty(c.getPreviousName())).findFirst();
272 foundCapOpt.ifPresent(capabilityDataDefinition -> key[key.length - 1] = capabilityDataDefinition.getPreviousName());
273 newProps.put(buildCaLCapPropKey(key), properties);
276 private static String buildCaLCapPropKey(String[] keyArray) {
277 StringBuilder key = new StringBuilder();
278 for (int i = 0; i < keyArray.length; ++i) {
279 key.append(keyArray[i]);
280 if (i < keyArray.length - 1) {
281 key.append(ModelConverter.CAP_PROP_DELIM);
284 return key.toString();
287 private static void buildSetCapName(Map<String, ToscaElement> componentsCache, CapabilityDataDefinition capability,
288 ComponentInstanceDataDefinition instance,
289 Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
290 List<String> reducedPath = capability.getOwnerId() != null ? getReducedPathByOwner(capability.getPath(), capability.getOwnerId())
291 : getReducedPath(capability.getPath());
292 log.debug("reducedPath for ownerId {}, reducedPath {} ", capability.getOwnerId(), reducedPath);
293 reducedPath.remove(reducedPath.size() - 1);
294 ToscaElement originComponent = getOriginComponent(componentsCache, instance, originGetter);
295 String name = isRequiredToRepair(capability.getParentName()) ? extractNameFromUniqueId(capability.getUniqueId()) : capability.getParentName();
296 StringBuilder repairedName = buildSubstitutedName(componentsCache, originComponent, reducedPath, originGetter);
297 log.debug("#buildSetCapName - The name for the capability was built: {}", repairedName);
298 capability.setName(repairedName.append(name).toString());
299 if (isRequiredToRepair(capability.getPreviousName())) {
300 capability.setPreviousName(capability.getName().substring(capability.getName().indexOf(PATH_DELIMITER) + 1));
302 if (isRequiredToRepair(capability.getParentName())) {
303 capability.setParentName(name);
307 private static void buildSetReqName(Map<String, ToscaElement> componentsCache, RequirementDataDefinition requirement,
308 ComponentInstanceDataDefinition instance,
309 Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
310 List<String> reducedPath = requirement.getOwnerId() != null ? getReducedPathByOwner(requirement.getPath(), requirement.getOwnerId())
311 : getReducedPath(requirement.getPath());
312 log.debug("reducedPath for ownerId {}, reducedPath {} ", requirement.getOwnerId(), reducedPath);
313 reducedPath.remove(reducedPath.size() - 1);
314 ToscaElement originComponent = getOriginComponent(componentsCache, instance, originGetter);
316 isRequiredToRepair(requirement.getParentName()) ? extractNameFromUniqueId(requirement.getUniqueId()) : requirement.getParentName();
317 StringBuilder repairedName = buildSubstitutedName(componentsCache, originComponent, reducedPath, originGetter);
318 log.debug("#buildSetReqName - The name for the capability was built: ", repairedName);
319 requirement.setName(repairedName.append(name).toString());
320 if (isRequiredToRepair(requirement.getPreviousName())) {
321 requirement.setPreviousName(requirement.getName().substring(requirement.getName().indexOf(PATH_DELIMITER) + 1));
323 if (isRequiredToRepair(requirement.getParentName())) {
324 requirement.setParentName(name);
328 private static String extractNameFromUniqueId(String uniqueId) {
329 String[] uid = uniqueId.split("\\.");
330 return uid[uid.length - 1];
333 private static StringBuilder buildSubstitutedName(Map<String, ToscaElement> componentsCache, ToscaElement originComponent, List<String> path,
334 Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
335 StringBuilder substitutedName = new StringBuilder();
336 log.debug("#buildSubstitutedName");
337 if (isNotEmpty(path) && isTopologyTemplateNotCvfc(originComponent)) {
338 log.debug("#buildSubstitutedName");
339 List<String> reducedPath = getReducedPath(path);
340 Collections.reverse(reducedPath);
341 appendNameRecursively(componentsCache, originComponent, reducedPath.iterator(), substitutedName, originGetter);
343 return substitutedName;
346 private static boolean isTopologyTemplateNotCvfc(ToscaElement originComponent) {
347 return originComponent.getToscaType() == ToscaElementTypeEnum.TOPOLOGY_TEMPLATE && originComponent.getResourceType() != ResourceTypeEnum.CVFC;
350 private static ToscaElement getOriginComponent(Map<String, ToscaElement> componentsCache, ComponentInstanceDataDefinition instance,
351 Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
352 if (componentsCache.containsKey(getActualComponentUid(instance))) {
353 return componentsCache.get(getActualComponentUid(instance));
355 ToscaElement origin = originGetter.apply(instance);
356 componentsCache.put(origin.getUniqueId(), origin);
360 public static String getActualComponentUid(ComponentInstanceDataDefinition instance) {
361 return instance.getIsProxy() ? instance.getSourceModelUid() : instance.getComponentUid();
364 private static List<String> getReducedPath(List<String> path) {
365 return path.stream().distinct().collect(Collectors.toList());
368 private static void appendNameRecursively(Map<String, ToscaElement> componentsCache, ToscaElement originComponent,
369 Iterator<String> instanceIdIter, StringBuilder substitutedName,
370 Function<ComponentInstanceDataDefinition, ToscaElement> originGetter) {
371 log.debug("#appendNameRecursively");
372 if (isTopologyTemplateNotCvfc(originComponent) && MapUtils.isNotEmpty(((TopologyTemplate) originComponent).getComponentInstances())
373 && instanceIdIter.hasNext()) {
374 String ownerId = instanceIdIter.next();
375 Optional<ComponentInstanceDataDefinition> instanceOpt = ((TopologyTemplate) originComponent).getComponentInstances().values().stream()
376 .filter(i -> i.getUniqueId().equals(ownerId)).findFirst();
377 if (instanceOpt.isPresent()) {
378 substitutedName.append(instanceOpt.get().getNormalizedName()).append(PATH_DELIMITER);
379 ToscaElement getOriginRes = getOriginComponent(componentsCache, instanceOpt.get(), originGetter);
380 appendNameRecursively(componentsCache, getOriginRes, instanceIdIter, substitutedName, originGetter);
381 } else if (MapUtils.isNotEmpty(((TopologyTemplate) originComponent).getGroups())) {
382 Optional<GroupDataDefinition> groupOpt = ((TopologyTemplate) originComponent).getGroups().values().stream()
383 .filter(g -> g.getUniqueId().equals(ownerId)).findFirst();
384 groupOpt.ifPresent(groupDataDefinition -> substitutedName.append(groupDataDefinition.getName()).append(PATH_DELIMITER));
386 log.debug("Failed to find an capability owner with uniqueId {} on a component with uniqueId {}", ownerId,
387 originComponent.getUniqueId());
392 private static List<String> getReducedPathByOwner(List<String> path, String ownerId) {
393 log.debug("ownerId {}, path {} ", ownerId, path);
394 if (CollectionUtils.isEmpty(path)) {
395 log.debug("cannot perform reduce by owner, path to component is empty");
398 if (isBlank(ownerId)) {
399 log.debug("cannot perform reduce by owner, component owner is empty");
403 Map map = path.stream()
404 .collect(Collectors.toMap(it -> dropLast(it, PATH_DELIMITER), Function.identity(), (a, b) -> a.endsWith(ownerId) ? a : b));
405 //reduce list&duplicates and preserve order
406 return path.stream().distinct().filter(it -> map.values().contains(it)).collect(Collectors.toList());
409 private static String dropLast(String path, String delimiter) {
410 if (isBlank(path) || isBlank(delimiter)) {
413 return path.substring(0, path.lastIndexOf(delimiter));