2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 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.tosca;
22 import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
23 import static org.apache.commons.lang3.StringUtils.isBlank;
24 import static org.apache.commons.lang3.StringUtils.isNoneBlank;
26 import com.google.common.collect.Iterables;
27 import com.google.common.collect.Maps;
28 import fj.data.Either;
29 import java.util.ArrayList;
30 import java.util.Collections;
31 import java.util.HashMap;
32 import java.util.Iterator;
33 import java.util.List;
35 import java.util.Optional;
36 import java.util.function.Function;
37 import java.util.stream.Collectors;
38 import org.apache.commons.collections.CollectionUtils;
39 import org.apache.commons.collections.MapUtils;
40 import org.apache.commons.lang3.StringUtils;
41 import org.apache.commons.lang3.tuple.ImmutablePair;
42 import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition;
43 import org.openecomp.sdc.be.datatypes.elements.RequirementDataDefinition;
44 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
45 import org.openecomp.sdc.be.model.CapabilityDefinition;
46 import org.openecomp.sdc.be.model.Component;
47 import org.openecomp.sdc.be.model.ComponentInstance;
48 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
49 import org.openecomp.sdc.be.model.ComponentParametersView;
50 import org.openecomp.sdc.be.model.DataTypeDefinition;
51 import org.openecomp.sdc.be.model.GroupDefinition;
52 import org.openecomp.sdc.be.model.PropertyDefinition;
53 import org.openecomp.sdc.be.model.RequirementDefinition;
54 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
55 import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
56 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
57 import org.openecomp.sdc.be.model.utils.ComponentUtilities;
58 import org.openecomp.sdc.be.tosca.ToscaUtils.SubstitutionEntry;
59 import org.openecomp.sdc.be.tosca.model.SubstitutionMapping;
60 import org.openecomp.sdc.be.tosca.model.ToscaCapability;
61 import org.openecomp.sdc.be.tosca.model.ToscaNodeTemplate;
62 import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
63 import org.openecomp.sdc.be.tosca.model.ToscaProperty;
64 import org.openecomp.sdc.be.tosca.model.ToscaRequirement;
65 import org.openecomp.sdc.be.tosca.model.ToscaTemplateCapability;
66 import org.openecomp.sdc.common.log.wrappers.Logger;
67 import org.springframework.beans.factory.annotation.Autowired;
68 import org.springframework.context.annotation.Scope;
71 * Allows to convert requirements\capabilities of a component to requirements\capabilities of a substitution mappings section of a tosca template
73 @org.springframework.stereotype.Component("capabilty-requirement-convertor")
74 @Scope(value = "singleton")
75 public class CapabilityRequirementConverter {
77 private static final String NO_CAPABILITIES = "No Capabilities for node type";
78 private static final String NO_REQUIREMENTS = "No Requirements for node type";
79 private static final Logger logger = Logger.getLogger(CapabilityRequirementConverter.class);
80 private static final String PATH_DELIMITER = ".";
81 private static final String FAILED_TO_FIND_CI_IN_PATH = "Failed to find ci in the path is {} component {}";
82 private static CapabilityRequirementConverter instance;
84 private ToscaOperationFacade toscaOperationFacade;
86 private PropertyConvertor propertyConvertor;
88 public CapabilityRequirementConverter() {
91 public static synchronized CapabilityRequirementConverter getInstance() {
92 if (instance == null) {
93 instance = new CapabilityRequirementConverter();
98 public String buildCapabilityNameForComponentInstance(Map<String, Component> componentCache, ComponentInstance componentInstance,
99 CapabilityDefinition c) {
100 String prefix = buildCapReqNamePrefix(componentInstance.getNormalizedName());
101 if (ComponentUtilities.isNotUpdatedCapReqName(prefix, c.getName(), c.getPreviousName())) {
102 return buildSubstitutedName(componentCache, c.getName(), c.getPreviousName(), c.getPath(), c.getOwnerId(), componentInstance).left()
103 .orValue(c.getName());
105 return c.getPreviousName();
108 public String buildRequirementNameForComponentInstance(Map<String, Component> componentCache, ComponentInstance componentInstance,
109 RequirementDefinition r) {
110 String prefix = buildCapReqNamePrefix(componentInstance.getNormalizedName());
111 if (ComponentUtilities.isNotUpdatedCapReqName(prefix, r.getName(), r.getPreviousName())) {
112 return buildSubstitutedName(componentCache, r.getName(), r.getPreviousName(), r.getPath(), r.getOwnerId(), componentInstance).left()
113 .orValue(r.getName());
115 return r.getPreviousName();
118 private String buildCapReqNamePrefix(String normalizedName) {
119 return normalizedName + PATH_DELIMITER;
123 * Allows to convert capabilities of a component to capabilities of a substitution mappings section of a tosca template
125 * @param componentInstance
127 * @param nodeTemplate
130 public Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceCapabilities(ComponentInstance componentInstance,
131 Map<String, DataTypeDefinition> dataTypes,
132 ToscaNodeTemplate nodeTemplate) {
133 Map<String, List<CapabilityDefinition>> capabilitiesInst = componentInstance.getCapabilities();
134 Map<String, Component> componentCache = new HashMap<>();
135 if (capabilitiesInst != null && !capabilitiesInst.isEmpty()) {
136 Map<String, ToscaTemplateCapability> capabilities = new HashMap<>();
137 capabilitiesInst.entrySet().forEach(e -> {
138 List<CapabilityDefinition> capList = e.getValue();
139 if (capList != null && !capList.isEmpty()) {
140 capList.stream().forEach(c -> convertOverridenProperties(componentInstance, dataTypes, capabilities, c,
141 buildCapabilityNameForComponentInstance(componentCache, componentInstance, c)));
144 if (MapUtils.isNotEmpty(capabilities)) {
145 nodeTemplate.setCapabilities(capabilities);
148 return Either.left(nodeTemplate);
151 private void convertOverridenProperties(ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes,
152 Map<String, ToscaTemplateCapability> capabilties, CapabilityDefinition c, String capabilityName) {
153 if (isNotEmpty(c.getProperties())) {
154 c.getProperties().stream().filter(p -> p.getValue() != null || p.getDefaultValue() != null)
155 .forEach(p -> convertOverriddenProperty(componentInstance, dataTypes, capabilties, p, capabilityName));
159 private void convertOverriddenProperty(ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes,
160 Map<String, ToscaTemplateCapability> capabilties, ComponentInstanceProperty p, String capabilityName) {
161 if (logger.isDebugEnabled()) {
162 logger.debug("Exist d property {} for capability {} with value {}", p.getName(), capabilityName, p.getValue());
164 ToscaTemplateCapability toscaTemplateCapability = capabilties.computeIfAbsent(capabilityName, key -> new ToscaTemplateCapability());
165 Map<String, Object> toscaCapProp = toscaTemplateCapability.getProperties();
166 if (toscaCapProp == null) {
167 toscaCapProp = new HashMap<>();
169 Object convertedValue = convertInstanceProperty(dataTypes, componentInstance, p);
170 toscaCapProp.put(p.getName(), convertedValue);
171 toscaTemplateCapability.setProperties(toscaCapProp);
174 private Object convertInstanceProperty(Map<String, DataTypeDefinition> dataTypes, ComponentInstance componentInstance,
175 ComponentInstanceProperty prop) {
176 logger.debug("Convert property {} for instance {}", prop.getName(), componentInstance.getUniqueId());
177 String propValue = prop.getValue() == null ? prop.getDefaultValue() : prop.getValue();
178 return propertyConvertor.convertToToscaObject(prop, propValue, dataTypes, false);
182 * Allows to convert requirements of a node type to tosca template requirements representation
188 public Either<ToscaNodeType, ToscaError> convertRequirements(Map<String, Component> componentsCache, Component component,
189 ToscaNodeType nodeType) {
190 List<Map<String, ToscaRequirement>> toscaRequirements = convertRequirementsAsList(componentsCache, component);
191 if (!toscaRequirements.isEmpty()) {
192 nodeType.setRequirements(toscaRequirements);
194 logger.debug("Finish convert Requirements for node type");
195 return Either.left(nodeType);
199 * Allows to convert component requirements to the tosca template substitution mappings requirements
201 * @param componentsCache
203 * @param substitutionMappings
206 public Either<SubstitutionMapping, ToscaError> convertSubstitutionMappingRequirements(Map<String, Component> componentsCache, Component component,
207 SubstitutionMapping substitutionMappings) {
208 Either<SubstitutionMapping, ToscaError> result = Either.left(substitutionMappings);
209 Either<Map<String, String[]>, ToscaError> toscaRequirementsRes = convertSubstitutionMappingRequirementsAsMap(componentsCache, component);
210 if (toscaRequirementsRes.isRight()) {
211 result = Either.right(toscaRequirementsRes.right().value());
212 logger.debug("Failed convert requirements for the component {}. ", component.getName());
213 } else if (MapUtils.isNotEmpty(toscaRequirementsRes.left().value())) {
214 substitutionMappings.setRequirements(toscaRequirementsRes.left().value());
215 result = Either.left(substitutionMappings);
216 logger.debug("Finish convert requirements for the component {}. ", component.getName());
222 * Allows to convert requirements of a server proxy node type to tosca template requirements
224 * @param instanceProxy
225 * @return converted tosca template requirements
227 List<Map<String, ToscaRequirement>> convertProxyRequirements(Map<String, Component> componentCache, ComponentInstance instanceProxy) {
228 Map<String, List<RequirementDefinition>> requirements = instanceProxy.getRequirements();
229 List<Map<String, ToscaRequirement>> toscaRequirements = new ArrayList<>();
230 if (requirements != null) {
231 requirements.entrySet().stream().flatMap(e -> e.getValue().stream()).forEach(req -> {
232 ImmutablePair<String, ToscaRequirement> pair = convertProxyRequirement(
233 buildRequirementNameForComponentInstance(componentCache, instanceProxy, req), req);
234 Map<String, ToscaRequirement> requirement = new HashMap<>();
235 requirement.put(pair.left, pair.right);
236 toscaRequirements.add(requirement);
239 logger.debug(NO_REQUIREMENTS);
241 return toscaRequirements;
244 private ImmutablePair<String, ToscaRequirement> convertProxyRequirement(String requirementName, RequirementDefinition r) {
245 ToscaRequirement toscaRequirement = createToscaRequirement(r);
246 return new ImmutablePair<>(requirementName, toscaRequirement);
249 private List<Map<String, ToscaRequirement>> convertRequirementsAsList(Map<String, Component> componentsCache, Component component) {
250 Map<String, List<RequirementDefinition>> requirements = component.getRequirements();
251 List<Map<String, ToscaRequirement>> toscaRequirements = new ArrayList<>();
252 if (requirements != null) {
253 for (Map.Entry<String, List<RequirementDefinition>> entry : requirements.entrySet()) {
254 entry.getValue().stream().filter(r -> filter(component, r.getOwnerId())).forEach(r -> {
255 ImmutablePair<String, ToscaRequirement> pair = convertRequirement(componentsCache, component,
256 ModelConverter.isAtomicComponent(component), r);
257 Map<String, ToscaRequirement> requirement = new HashMap<>();
258 requirement.put(pair.left, pair.right);
259 toscaRequirements.add(requirement);
261 logger.debug("Finish convert Requirements for node type");
264 logger.debug(NO_REQUIREMENTS);
266 return toscaRequirements;
269 private boolean filter(Component component, String ownerId) {
270 return !ModelConverter.isAtomicComponent(component) || isNodeTypeOwner(component, ownerId) || (ModelConverter.isAtomicComponent(component)
274 private boolean isNodeTypeOwner(Component component, String ownerId) {
275 return ModelConverter.isAtomicComponent(component) && component.getUniqueId().equals(ownerId);
278 private String dropLast(String path, String delimiter) {
279 if (isBlank(path) || isBlank(delimiter)) {
282 return path.substring(0, path.lastIndexOf(delimiter));
285 private Either<Map<String, String[]>, ToscaError> convertSubstitutionMappingRequirementsAsMap(Map<String, Component> componentsCache,
286 Component component) {
287 Map<String, List<RequirementDefinition>> requirements = component.getRequirements();
288 Either<Map<String, String[]>, ToscaError> result;
289 if (requirements != null) {
290 result = buildAddSubstitutionMappingsRequirements(componentsCache, component, requirements);
292 result = Either.left(Maps.newHashMap());
293 logger.debug("No requirements for substitution mappings section of a tosca template of the component {}. ", component.getName());
298 private Either<Map<String, String[]>, ToscaError> buildAddSubstitutionMappingsRequirements(Map<String, Component> componentsCache,
300 Map<String, List<RequirementDefinition>> requirements) {
301 Map<String, String[]> toscaRequirements = new HashMap<>();
302 Either<Map<String, String[]>, ToscaError> result = null;
303 for (Map.Entry<String, List<RequirementDefinition>> entry : requirements.entrySet()) {
304 Optional<RequirementDefinition> failedToAddRequirement = addExternalToToscaRequirements(componentsCache, toscaRequirements, component, entry.getValue());
305 if (failedToAddRequirement.isPresent()) {
306 logger.debug("Failed to convert requirement {} for substitution mappings section of a tosca template of the component {}. ",
307 failedToAddRequirement.get().getName(), component.getName());
308 result = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
310 logger.debug("Finish convert requirements for the component {}. ", component.getName());
312 if (result == null) {
313 result = Either.left(toscaRequirements);
318 private Optional<RequirementDefinition> addExternalToToscaRequirements(final Map<String, Component> componentsCache,
319 final Map<String, String[]> toscaRequirements, final Component component, final List<RequirementDefinition> requirements) {
320 return requirements.stream().filter(RequirementDefinition::isExternal).filter(
322 (StringUtils.isEmpty(r.getExternalName()) ?
323 addEntry(componentsCache, toscaRequirements, component, new SubstitutionEntry(r.getName(), r.getParentName(), ""),
324 r.getPreviousName(), r.getOwnerId(), r.getPath()):
325 addEntry(componentsCache, toscaRequirements, component, new SubstitutionEntry(r.getExternalName(), r.getPreviousName() == null ? r.getName(): r.getPreviousName(), ""),
326 r.getPreviousName(), r.getOwnerId(), r.getPath(), false))
330 private Either<Map<String, String[]>, ToscaError> buildAddSubstitutionMappingsCapabilities(Map<String, Component> componentsCache,
332 Map<String, List<CapabilityDefinition>> capabilities) {
333 Map<String, String[]> toscaCapabilities = new HashMap<>();
334 Either<Map<String, String[]>, ToscaError> result = null;
335 for (Map.Entry<String, List<CapabilityDefinition>> entry : capabilities.entrySet()) {
336 Optional<CapabilityDefinition> failedToAddRequirement = addExternalToToscaCapabilities(componentsCache, toscaCapabilities, component, entry.getValue());
337 if (failedToAddRequirement.isPresent()) {
338 logger.debug("Failed to convert capability {} for substitution mappings section of a tosca template of the component {}. ",
339 failedToAddRequirement.get().getName(), component.getName());
340 result = Either.right(ToscaError.NODE_TYPE_CAPABILITY_ERROR);
342 logger.debug("Finish convert capabilities for the component {}. ", component.getName());
344 if (result == null) {
345 result = Either.left(toscaCapabilities);
350 private Optional<CapabilityDefinition> addExternalToToscaCapabilities(final Map<String, Component> componentsCache,
351 final Map<String, String[]> toscaCapabilities, final Component component, final List<CapabilityDefinition> requirements) {
352 return requirements.stream()
353 .filter(CapabilityDataDefinition::isExternal)
355 (StringUtils.isEmpty(c.getExternalName()) ?
356 addEntry(componentsCache, toscaCapabilities, component, new SubstitutionEntry(c.getName(), c.getParentName(), ""),
357 c.getPreviousName(), c.getOwnerId(), c.getPath()):
358 addEntry(componentsCache, toscaCapabilities, component, new SubstitutionEntry(c.getName(), c.getParentName(), ""),
359 c.getPreviousName(), c.getOwnerId(), c.getPath(), false))
363 private boolean addEntry(Map<String, Component> componentsCache, Map<String, String[]> capReqMap, Component component, SubstitutionEntry entry,
364 String previousName, String ownerId, List<String> path) {
365 return addEntry(componentsCache, capReqMap, component, entry, previousName, ownerId, path, shouldBuildSubstitutionName(component, path));
368 private boolean addEntry(final Map<String, Component> componentsCache, Map<String, String[]> capReqMap, final Component component,
369 final SubstitutionEntry entry, final String previousName, final String ownerId, final List<String> path, final boolean shouldBuildSubstitutionName) {
370 if (shouldBuildSubstitutionName && !buildSubstitutedNamePerInstance(componentsCache,
371 component, entry.getFullName(), previousName, path, ownerId, entry)) {
374 logger.debug("The requirement/capability {} belongs to the component {} ", entry.getFullName(),
375 component.getUniqueId());
376 if (StringUtils.isNotEmpty(entry.getSourceName())) {
377 addEntry(capReqMap, component, path, entry);
379 logger.debug("Finish convert the requirement/capability {} for the component {}. ", entry.getFullName(),
380 component.getName());
384 private boolean shouldBuildSubstitutionName(Component component, List<String> path) {
385 return ToscaUtils.isNotComplexVfc(component) && isNotEmpty(path) && path.iterator().hasNext();
388 private boolean buildSubstitutedNamePerInstance(Map<String, Component> componentsCache, Component component, String name, String previousName,
389 List<String> path, String ownerId, SubstitutionEntry entry) {
393 if (CollectionUtils.isNotEmpty(component.getGroups())) {
394 Optional<GroupDefinition> groupOpt = component.getGroups().stream().filter(g -> g.getUniqueId().equals(ownerId)).findFirst();
395 if (groupOpt.isPresent()) {
396 prefix = buildCapReqNamePrefix(groupOpt.get().getNormalizedName());
397 if (ComponentUtilities.isNotUpdatedCapReqName(prefix, name, previousName)) {
399 fullName = prefix + sourceName;
401 sourceName = previousName;
404 entry.setFullName(fullName);
405 entry.setSourceName(sourceName);
406 entry.setOwner(groupOpt.get().getNormalizedName());
410 Optional<ComponentInstance> ci = component.safeGetComponentInstances().stream().filter(c -> c.getUniqueId().equals(Iterables.getLast(path)))
412 if (!ci.isPresent()) {
413 logger.debug(FAILED_TO_FIND_CI_IN_PATH, path, component.getUniqueId());
414 Collections.reverse(path);
415 logger.debug("try to reverse path {} component {}", path, component.getUniqueId());
416 ci = component.safeGetComponentInstances().stream().filter(c -> c.getUniqueId().equals(Iterables.getLast(path))).findFirst();
418 if (ci.isPresent()) {
419 prefix = buildCapReqNamePrefix(ci.get().getNormalizedName());
420 if (ComponentUtilities.isNotUpdatedCapReqName(prefix, name, previousName)) {
421 Either<String, Boolean> buildSubstitutedName = buildSubstitutedName(componentsCache, name, previousName, path, ownerId, ci.get());
422 if (buildSubstitutedName.isRight()) {
423 logger.debug("Failed buildSubstitutedName name {} path {} component {}", name, path, component.getUniqueId());
426 sourceName = buildSubstitutedName.left().value();
427 fullName = prefix + sourceName;
429 sourceName = previousName;
432 entry.setFullName(fullName);
433 entry.setSourceName(sourceName);
435 logger.debug(FAILED_TO_FIND_CI_IN_PATH, path, component.getUniqueId());
441 private void addEntry(Map<String, String[]> toscaRequirements, Component component, List<String> capPath, SubstitutionEntry entry) {
442 Optional<ComponentInstance> findFirst = component.safeGetComponentInstances().stream()
443 .filter(ci -> ci.getUniqueId().equals(Iterables.getLast(capPath))).findFirst();
444 findFirst.ifPresent(componentInstance -> entry.setOwner(componentInstance.getName()));
445 if (StringUtils.isNotEmpty(entry.getOwner()) && StringUtils.isNotEmpty(entry.getSourceName())) {
446 toscaRequirements.put(entry.getFullName(), new String[]{entry.getOwner(), entry.getSourceName()});
450 public Either<String, Boolean> buildSubstitutedName(Map<String, Component> componentsCache, String name, String previousName, List<String> path,
451 String ownerId, ComponentInstance instance) {
452 if (StringUtils.isNotEmpty(previousName)) {
453 return Either.left(name);
455 Either<Component, Boolean> getOriginRes = getOriginComponent(componentsCache, instance);
456 if (getOriginRes.isRight()) {
458 .debug("Failed to build substituted name for the capability/requirement {}. Failed to get an origin component with uniqueId {}", name,
459 instance.getComponentUid());
460 return Either.right(false);
462 List<String> reducedPath = ownerId != null ? getReducedPathByOwner(path, ownerId) : getReducedPath(path);
463 logger.debug("reducedPath for ownerId {}, reducedPath {} ", ownerId, reducedPath);
464 reducedPath.remove(reducedPath.size() - 1);
465 return buildSubstitutedName(componentsCache, getOriginRes.left().value(), reducedPath, name, previousName);
468 private String buildReqNamePerOwnerByPath(Map<String, Component> componentsCache, Component component, RequirementDefinition r) {
469 return buildCapReqNamePerOwnerByPath(componentsCache, component, r.getName(), r.getPreviousName(), r.getPath());
472 private ImmutablePair<String, ToscaRequirement> convertRequirement(Map<String, Component> componentsCache, Component component,
473 boolean isNodeType, RequirementDefinition r) {
475 if (StringUtils.isEmpty(r.getExternalName())){
477 if (!isNodeType && ToscaUtils.isNotComplexVfc(component)) {
478 name = buildReqNamePerOwnerByPath(componentsCache, component, r);
481 name = r.getExternalName();
484 logger.debug("the requirement {} belongs to resource {} ", name, component.getUniqueId());
485 ToscaRequirement toscaRequirement = createToscaRequirement(r);
486 return new ImmutablePair<>(name, toscaRequirement);
489 private ToscaRequirement createToscaRequirement(RequirementDefinition r) {
490 ToscaRequirement toscaRequirement = new ToscaRequirement();
491 List<Object> occurrences = new ArrayList<>();
492 occurrences.add(Integer.valueOf(r.getMinOccurrences()));
493 if (r.getMaxOccurrences().equals(RequirementDataDefinition.MAX_OCCURRENCES)) {
494 occurrences.add(r.getMaxOccurrences());
496 occurrences.add(Integer.valueOf(r.getMaxOccurrences()));
498 toscaRequirement.setOccurrences(occurrences);
499 toscaRequirement.setNode(r.getNode());
500 toscaRequirement.setCapability(r.getCapability());
501 toscaRequirement.setRelationship(r.getRelationship());
502 return toscaRequirement;
506 * Allows to convert capabilities of a node type to tosca template capabilities
512 public Map<String, ToscaCapability> convertCapabilities(Map<String, Component> componentsCache, Component component,
513 Map<String, DataTypeDefinition> dataTypes) {
514 Map<String, List<CapabilityDefinition>> capabilities = component.getCapabilities();
515 Map<String, ToscaCapability> toscaCapabilities = new HashMap<>();
516 if (capabilities != null) {
517 boolean isNodeType = ModelConverter.isAtomicComponent(component);
518 for (Map.Entry<String, List<CapabilityDefinition>> entry : capabilities.entrySet()) {
519 entry.getValue().stream().filter(c -> filter(component, c.getOwnerId()))
520 .forEach(c -> convertCapability(componentsCache, component, toscaCapabilities, isNodeType, c, dataTypes, c.getName()));
523 logger.debug(NO_CAPABILITIES);
525 return toscaCapabilities;
529 * Allows to convert capabilities of a server proxy node type to tosca template capabilities
531 * @param instanceProxy
535 public Map<String, ToscaCapability> convertProxyCapabilities(Map<String, Component> componentCache, ComponentInstance instanceProxy,
536 Map<String, DataTypeDefinition> dataTypes) {
537 Map<String, List<CapabilityDefinition>> capabilities = instanceProxy.getCapabilities();
538 Map<String, ToscaCapability> toscaCapabilities = new HashMap<>();
539 if (capabilities != null) {
540 for (Map.Entry<String, List<CapabilityDefinition>> entry : capabilities.entrySet()) {
541 entry.getValue().stream().forEach(c -> convertProxyCapability(toscaCapabilities, c, dataTypes,
542 buildCapabilityNameForComponentInstance(componentCache, instanceProxy, c)));
545 logger.debug(NO_CAPABILITIES);
547 return toscaCapabilities;
551 * Allows to convert component capabilities to the tosca template substitution mappings capabilities
553 * @param componentsCache
557 public Either<Map<String, String[]>, ToscaError> convertSubstitutionMappingCapabilities(Map<String, Component> componentsCache,
558 Component component) {
559 Map<String, List<CapabilityDefinition>> capabilities = component.getCapabilities();
560 Either<Map<String, String[]>, ToscaError> res;
561 if (capabilities != null) {
562 res = buildAddSubstitutionMappingsCapabilities(componentsCache, component, capabilities);
564 res = Either.left(Maps.newHashMap());
565 logger.debug(NO_CAPABILITIES);
570 private String buildCapNamePerOwnerByPath(Map<String, Component> componentsCache, CapabilityDefinition c, Component component) {
571 return buildCapReqNamePerOwnerByPath(componentsCache, component, c.getName(), c.getPreviousName(), c.getPath());
574 private void convertProxyCapability(Map<String, ToscaCapability> toscaCapabilities, CapabilityDefinition c,
575 Map<String, DataTypeDefinition> dataTypes, String capabilityName) {
576 createToscaCapability(toscaCapabilities, c, dataTypes, capabilityName);
579 private void convertCapability(Map<String, Component> componentsCache, Component component, Map<String, ToscaCapability> toscaCapabilities,
580 boolean isNodeType, CapabilityDefinition c, Map<String, DataTypeDefinition> dataTypes, String capabilityName) {
582 if (StringUtils.isEmpty(c.getExternalName())) {
583 name = isNoneBlank(capabilityName) ? capabilityName : c.getName();
584 if (!isNodeType && ToscaUtils.isNotComplexVfc(component)) {
585 name = buildCapNamePerOwnerByPath(componentsCache, c, component);
588 name = c.getExternalName();
590 logger.debug("The capability {} belongs to resource {} ", name, component.getUniqueId());
591 createToscaCapability(toscaCapabilities, c, dataTypes, name);
594 private void createToscaCapability(Map<String, ToscaCapability> toscaCapabilities, CapabilityDefinition c,
595 Map<String, DataTypeDefinition> dataTypes, String name) {
596 ToscaCapability toscaCapability = new ToscaCapability();
597 toscaCapability.setDescription(c.getDescription());
598 toscaCapability.setType(c.getType());
599 List<Object> occurrences = new ArrayList<>();
600 occurrences.add(Integer.valueOf(c.getMinOccurrences()));
601 if (c.getMaxOccurrences().equals(CapabilityDataDefinition.MAX_OCCURRENCES)) {
602 occurrences.add(c.getMaxOccurrences());
604 occurrences.add(Integer.valueOf(c.getMaxOccurrences()));
606 toscaCapability.setOccurrences(occurrences);
607 toscaCapability.setValid_source_types(c.getValidSourceTypes());
608 List<ComponentInstanceProperty> properties = c.getProperties();
609 if (isNotEmpty(properties)) {
610 Map<String, ToscaProperty> toscaProperties = new HashMap<>();
611 for (PropertyDefinition property : properties) {
612 ToscaProperty toscaProperty = propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.CAPABILITY);
613 toscaProperties.put(property.getName(), toscaProperty);
615 toscaCapability.setProperties(toscaProperties);
617 toscaCapabilities.put(name, toscaCapability);
620 private String buildCapReqNamePerOwnerByPath(Map<String, Component> componentsCache, Component component, String name, String previousName,
622 if (CollectionUtils.isEmpty(path)) {
625 String ownerId = path.get(path.size() - 1);
627 if (CollectionUtils.isNotEmpty(component.getGroups())) {
628 Optional<GroupDefinition> groupOpt = component.getGroups().stream().filter(g -> g.getUniqueId().equals(ownerId)).findFirst();
629 if (groupOpt.isPresent()) {
630 prefix = buildCapReqNamePrefix(groupOpt.get().getNormalizedName());
631 if (ComponentUtilities.isNotUpdatedCapReqName(prefix, name, previousName)) {
632 return prefix + name;
637 Optional<ComponentInstance> ci = component.safeGetComponentInstances().stream().filter(c -> c.getUniqueId().equals(Iterables.getLast(path)))
639 if (!ci.isPresent()) {
640 logger.debug(FAILED_TO_FIND_CI_IN_PATH, path, component.getUniqueId());
641 Collections.reverse(path);
642 logger.debug("try to reverse path {} component {}", path, component.getUniqueId());
643 ci = component.safeGetComponentInstances().stream().filter(c -> c.getUniqueId().equals(Iterables.getLast(path))).findFirst();
645 if (ci.isPresent()) {
646 prefix = buildCapReqNamePrefix(ci.get().getNormalizedName());
647 if (ComponentUtilities.isNotUpdatedCapReqName(prefix, name, previousName)) {
648 Either<String, Boolean> buildSubstitutedName = buildSubstitutedName(componentsCache, name, previousName, path, ownerId, ci.get());
649 if (buildSubstitutedName.isRight()) {
650 logger.debug("Failed buildSubstitutedName name {} path {} component {}", name, path, component.getUniqueId());
652 return prefix + buildSubstitutedName.left().value();
656 return StringUtils.EMPTY;
660 * Allows to build substituted name of capability\requirement of the origin component instance according to the path
662 * @param componentsCache
663 * @param originComponent
666 * @param previousName
669 public Either<String, Boolean> buildSubstitutedName(Map<String, Component> componentsCache, Component originComponent, List<String> path,
670 String name, String previousName) {
671 return buildSubstitutedName(componentsCache, originComponent, path, name, previousName, null);
674 public Either<String, Boolean> buildSubstitutedName(Map<String, Component> componentsCache, Component originComponent, List<String> path,
675 String name, String previousName, String externalName) {
676 if (StringUtils.isNotEmpty(externalName)) {
677 return Either.left(externalName);
679 if (StringUtils.isNotEmpty(previousName)) {
680 return Either.left(name);
682 StringBuilder substitutedName = new StringBuilder();
683 boolean nameBuiltSuccessfully = true;
684 if (isNotEmpty(path) && ToscaUtils.isNotComplexVfc(originComponent)) {
685 List<String> reducedPath = getReducedPath(path);
686 Collections.reverse(reducedPath);
687 nameBuiltSuccessfully = appendNameRecursively(componentsCache, originComponent, reducedPath.iterator(), substitutedName);
689 return nameBuiltSuccessfully ? Either.left(substitutedName.append(name).toString()) : Either.right(nameBuiltSuccessfully);
692 protected List<String> getReducedPathByOwner(List<String> path, String ownerId) {
693 logger.debug("ownerId {}, path {} ", ownerId, path);
694 if (CollectionUtils.isEmpty(path)) {
695 logger.debug("cannot perform reduce by owner, path to component is empty");
698 if (isBlank(ownerId)) {
699 logger.debug("cannot perform reduce by owner, component owner is empty");
703 Map map = path.stream()
704 .collect(Collectors.toMap(it -> dropLast(it, PATH_DELIMITER), Function.identity(), (a, b) -> a.endsWith(ownerId) ? a : b));
705 //reduce list&duplicates and preserve order
706 return path.stream().distinct().filter(it -> map.values().contains(it)).collect(Collectors.toList());
709 private List<String> getReducedPath(List<String> path) {
710 return path.stream().distinct().collect(Collectors.toList());
713 private boolean appendNameRecursively(Map<String, Component> componentsCache, Component originComponent, Iterator<String> instanceIdIter,
714 StringBuilder substitutedName) {
715 if (isNotEmpty(originComponent.getComponentInstances()) && instanceIdIter.hasNext() && ToscaUtils.isNotComplexVfc(originComponent)) {
716 String ownerId = instanceIdIter.next();
717 Optional<ComponentInstance> instanceOpt = originComponent.getComponentInstances().stream().filter(i -> i.getUniqueId().equals(ownerId))
719 if (instanceOpt.isPresent()) {
720 substitutedName.append(instanceOpt.get().getNormalizedName()).append(PATH_DELIMITER);
721 Either<Component, Boolean> getOriginRes = getOriginComponent(componentsCache, instanceOpt.get());
722 if (getOriginRes.isRight()) {
725 appendNameRecursively(componentsCache, getOriginRes.left().value(), instanceIdIter, substitutedName);
726 } else if (CollectionUtils.isNotEmpty(originComponent.getGroups())) {
727 Optional<GroupDefinition> groupOpt = originComponent.getGroups().stream().filter(g -> g.getUniqueId().equals(ownerId)).findFirst();
728 if (!groupOpt.isPresent()) {
729 logger.debug("Failed to find an capability owner with uniqueId {} on a component with uniqueId {}", ownerId,
730 originComponent.getUniqueId());
733 substitutedName.append(groupOpt.get().getNormalizedName()).append(PATH_DELIMITER);
735 logger.debug("Failed to find an capability owner with uniqueId {} on a component with uniqueId {}", ownerId,
736 originComponent.getUniqueId());
743 Either<Component, Boolean> getOriginComponent(Map<String, Component> componentsCache, ComponentInstance instance) {
744 Either<Component, Boolean> result;
745 Either<Component, StorageOperationStatus> getOriginRes;
746 if (componentsCache.containsKey(instance.getActualComponentUid())) {
747 result = Either.left(componentsCache.get(instance.getActualComponentUid()));
749 ComponentParametersView filter = getFilter(instance);
750 getOriginRes = toscaOperationFacade.getToscaElement(instance.getActualComponentUid(), filter);
751 if (getOriginRes.isRight()) {
752 logger.debug("Failed to get an origin component with uniqueId {}", instance.getActualComponentUid());
753 result = Either.right(false);
755 result = Either.left(getOriginRes.left().value());
756 componentsCache.put(getOriginRes.left().value().getUniqueId(), getOriginRes.left().value());
762 private ComponentParametersView getFilter(ComponentInstance instance) {
763 ComponentParametersView filter = new ComponentParametersView(true);
764 filter.setIgnoreComponentInstances(false);
765 if (instance.getIsProxy()) {
766 filter.setIgnoreCapabilities(false);
767 filter.setIgnoreRequirements(false);
768 filter.setIgnoreCategories(false);
770 if (instance.getOriginType() == OriginTypeEnum.VF) {
771 filter.setIgnoreGroups(false);