summaryrefslogtreecommitdiffstats
path: root/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabiltyRequirementConvertor.java
diff options
context:
space:
mode:
Diffstat (limited to 'catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabiltyRequirementConvertor.java')
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabiltyRequirementConvertor.java1081
1 files changed, 554 insertions, 527 deletions
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabiltyRequirementConvertor.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabiltyRequirementConvertor.java
index 886b654b81..4dbbf925d3 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabiltyRequirementConvertor.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabiltyRequirementConvertor.java
@@ -20,50 +20,34 @@
package org.openecomp.sdc.be.tosca;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.stream.Collectors;
-
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import fj.data.Either;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition;
import org.openecomp.sdc.be.datatypes.elements.RequirementDataDefinition;
-import org.openecomp.sdc.be.model.CapabilityDefinition;
-import org.openecomp.sdc.be.model.Component;
-import org.openecomp.sdc.be.model.ComponentInstance;
-import org.openecomp.sdc.be.model.ComponentInstanceProperty;
-import org.openecomp.sdc.be.model.ComponentParametersView;
-import org.openecomp.sdc.be.model.DataTypeDefinition;
-import org.openecomp.sdc.be.model.PropertyDefinition;
-import org.openecomp.sdc.be.model.RequirementDefinition;
+import org.openecomp.sdc.be.model.*;
import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade;
import org.openecomp.sdc.be.model.jsontitan.utils.ModelConverter;
import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
import org.openecomp.sdc.be.tosca.ToscaUtils.SubstituitionEntry;
-import org.openecomp.sdc.be.tosca.model.SubstitutionMapping;
-import org.openecomp.sdc.be.tosca.model.ToscaCapability;
-import org.openecomp.sdc.be.tosca.model.ToscaNodeTemplate;
-import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
-import org.openecomp.sdc.be.tosca.model.ToscaProperty;
-import org.openecomp.sdc.be.tosca.model.ToscaRequirement;
-import org.openecomp.sdc.be.tosca.model.ToscaTemplateCapability;
+import org.openecomp.sdc.be.tosca.model.*;
import org.openecomp.sdc.common.util.ValidationUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
+import static org.apache.commons.lang3.StringUtils.*;
-import fj.data.Either;
/**
* Allows to convert requirements\capabilities of a component to requirements\capabilities of a substitution mappings section of a tosca template
*
@@ -71,502 +55,545 @@ import fj.data.Either;
@org.springframework.stereotype.Component("capabilty-requirement-convertor")
@Scope(value = "singleton")
public class CapabiltyRequirementConvertor {
-
- private static final String NO_CAPABILITIES = "No Capabilities for node type";
- private static CapabiltyRequirementConvertor instance;
- private static Logger logger = LoggerFactory.getLogger(CapabiltyRequirementConvertor.class.getName());
- public static final String PATH_DELIMITER = ".";
-
- @Autowired
- private ToscaOperationFacade toscaOperationFacade;
-
- protected CapabiltyRequirementConvertor() {}
-
- public static synchronized CapabiltyRequirementConvertor getInstance() {
- if (instance == null) {
- instance = new CapabiltyRequirementConvertor();
- }
- return instance;
- }
- /**
- * Allows to convert capabilities of a component to capabilities of a substitution mappings section of a tosca template
- * @param componentInstance
- * @param dataTypes
- * @param nodeTemplate
- * @return
- */
- public Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceCapabilties(ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, ToscaNodeTemplate nodeTemplate) {
-
- Map<String, List<CapabilityDefinition>> capabilitiesInst = componentInstance.getCapabilities();
- if (capabilitiesInst != null && !capabilitiesInst.isEmpty()) {
- Map<String, ToscaTemplateCapability> capabilties = new HashMap<>();
- capabilitiesInst.entrySet().forEach(e -> {
- List<CapabilityDefinition> capList = e.getValue();
- if (capList != null && !capList.isEmpty()) {
- capList.forEach(c -> convertOverridenProperties(componentInstance, dataTypes, capabilties, c));
- }
- });
- if (MapUtils.isNotEmpty(capabilties)) {
- nodeTemplate.setCapabilities(capabilties);
- }
- }
- return Either.left(nodeTemplate);
- }
-
- private void convertOverridenProperties(ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, Map<String, ToscaTemplateCapability> capabilties, CapabilityDefinition c) {
- if (CollectionUtils.isNotEmpty(c.getProperties())) {
- c.getProperties()
- .stream()
- .filter(p -> p.getValue() != null || p.getDefaultValue() != null)
- .forEach(p -> convertOverridenProperty(componentInstance, dataTypes, capabilties, c, p));
- }
- }
-
- private void convertOverridenProperty(ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, Map<String, ToscaTemplateCapability> capabilties, CapabilityDefinition c, ComponentInstanceProperty p) {
- if (logger.isDebugEnabled()) {
- logger.debug("Exist overriden property {} for capabity {} with value {}", p.getName(), c.getName(), p.getValue());
- }
- ToscaTemplateCapability toscaTemplateCapability = capabilties.get(c.getName());
- if (toscaTemplateCapability == null) {
- toscaTemplateCapability = new ToscaTemplateCapability();
- capabilties.put(c.getName(), toscaTemplateCapability);
- }
- Map<String, Object> toscaCapProp = toscaTemplateCapability.getProperties();
- if (toscaCapProp == null) {
- toscaCapProp = new HashMap<>();
- }
- Object convertedValue = convertInstanceProperty(dataTypes, componentInstance, p);
- toscaCapProp.put(p.getName(), convertedValue);
- toscaTemplateCapability.setProperties(toscaCapProp);
- }
-
- private Object convertInstanceProperty(Map<String, DataTypeDefinition> dataTypes, ComponentInstance componentInstance, ComponentInstanceProperty prop) {
- logger.debug("Convert property {} for instance {}", prop.getName(), componentInstance.getUniqueId());
- String propertyType = prop.getType();
- String innerType = null;
- if (prop.getSchema() != null && prop.getSchema().getProperty() != null) {
- innerType = prop.getSchema().getProperty().getType();
- }
- String propValue = prop.getValue() == null ? prop.getDefaultValue() : prop.getValue();
- return PropertyConvertor.getInstance().convertToToscaObject(propertyType, propValue, innerType, dataTypes);
- }
- /**
- * Allows to convert requirements of a node type to tosca template requirements representation
- * @param component
- * @param nodeType
- * @return
- */
- public Either<ToscaNodeType, ToscaError> convertRequirements(Component component, ToscaNodeType nodeType) {
- List<Map<String, ToscaRequirement>> toscaRequirements = convertRequirementsAsList(component);
- if (!toscaRequirements.isEmpty()) {
- nodeType.setRequirements(toscaRequirements);
- }
- logger.debug("Finish convert Requirements for node type");
-
- return Either.left(nodeType);
- }
-
- /**
- * Allows to convert component requirements to the tosca template substitution mappings requirements
- * @param componentsCache
- * @param component
- * @param substitutionMappings
- * @return
- */
- public Either<SubstitutionMapping, ToscaError> convertSubstitutionMappingRequirements(Map<String,Component> componentsCache, Component component, SubstitutionMapping substitutionMappings) {
- Either<SubstitutionMapping, ToscaError> result = Either.left(substitutionMappings);
- Either<Map<String, String[]>, ToscaError> toscaRequirementsRes = convertSubstitutionMappingRequirementsAsMap(componentsCache, component);
- if(toscaRequirementsRes.isRight()){
- result = Either.right(toscaRequirementsRes.right().value());
- logger.error("Failed convert requirements for the component {}. ", component.getName());
- } else if (MapUtils.isNotEmpty(toscaRequirementsRes.left().value())) {
- substitutionMappings.setRequirements(toscaRequirementsRes.left().value());
- result = Either.left(substitutionMappings);
- logger.debug("Finish convert requirements for the component {}. ", component.getName());
- }
- return result;
- }
-
- private List<Map<String, ToscaRequirement>> convertRequirementsAsList(Component component) {
- Map<String, List<RequirementDefinition>> requirements = component.getRequirements();
- List<Map<String, ToscaRequirement>> toscaRequirements = new ArrayList<>();
- if (requirements != null) {
- for (Map.Entry<String, List<RequirementDefinition>> entry : requirements.entrySet()) {
- entry.getValue().stream().filter(r -> filter(component, r.getOwnerId())).forEach(r -> {
- ImmutablePair<String, ToscaRequirement> pair = convertRequirement(component, ModelConverter.isAtomicComponent(component), r);
- Map<String, ToscaRequirement> requirement = new HashMap<>();
-
- requirement.put(pair.left, pair.right);
- toscaRequirements.add(requirement);
- });
- logger.debug("Finish convert Requirements for node type");
- }
- } else {
- logger.debug("No Requirements for node type");
- }
- return toscaRequirements;
- }
-
- private boolean filter(Component component, String ownerId) {
- return !ModelConverter.isAtomicComponent(component) || isNodeTypeOwner(component, ownerId) || (ModelConverter.isAtomicComponent(component) && ownerId == null);
- }
-
- private boolean isNodeTypeOwner(Component component, String ownerId) {
- return ModelConverter.isAtomicComponent(component) && component.getUniqueId().equals(ownerId);
- }
-
- private String getSubPathByLastDelimiterAppearance(String path) {
- return path.substring(path.lastIndexOf(PATH_DELIMITER) + 1);
- }
-
- private Either<Map<String, String[]>, ToscaError> convertSubstitutionMappingRequirementsAsMap(Map<String, Component> componentsCache, Component component) {
- Map<String, List<RequirementDefinition>> requirements = component.getRequirements();
- Either<Map<String, String[]>, ToscaError> result;
- if (requirements != null) {
- result = buildAddSubstitutionMappingsRequirements(componentsCache, component, requirements);
- } else {
- result = Either.left(Maps.newHashMap());
- logger.debug("No requirements for substitution mappings section of a tosca template of the component {}. ", component.getName());
- }
- return result;
- }
-
- private Either<Map<String, String[]>, ToscaError> buildAddSubstitutionMappingsRequirements(Map<String, Component> componentsCache, Component component, Map<String, List<RequirementDefinition>> requirements) {
-
- Map<String, String[]> toscaRequirements = new HashMap<>();
- Either<Map<String, String[]>, ToscaError> result = null;
- for (Map.Entry<String, List<RequirementDefinition>> entry : requirements.entrySet()) {
- Optional<RequirementDefinition> failedToAddRequirement = entry.getValue()
- .stream()
- .filter(r->!addEntry(componentsCache, toscaRequirements, component, r.getName(), r.getParentName(), r.getPath()))
- .findAny();
- if(failedToAddRequirement.isPresent()){
- logger.error("Failed to convert requirement {} for substitution mappings section of a tosca template of the component {}. ",
- failedToAddRequirement.get().getName(), component.getName());
- result = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
- }
- logger.debug("Finish convert requirements for the component {}. ", component.getName());
- }
- if(result == null){
- result = Either.left(toscaRequirements);
- }
- return result;
- }
-
- private Either<Map<String, String[]>, ToscaError> buildAddSubstitutionMappingsCapabilities(Map<String, Component> componentsCache, Component component, Map<String, List<CapabilityDefinition>> capabilities) {
-
- Map<String, String[]> toscaRequirements = new HashMap<>();
- Either<Map<String, String[]>, ToscaError> result = null;
- for (Map.Entry<String, List<CapabilityDefinition>> entry : capabilities.entrySet()) {
- Optional<CapabilityDefinition> failedToAddRequirement = entry.getValue()
- .stream()
- .filter(c->!addEntry(componentsCache, toscaRequirements, component, c.getName(), c.getParentName(), c.getPath()))
- .findAny();
- if(failedToAddRequirement.isPresent()){
- logger.error("Failed to convert capalility {} for substitution mappings section of a tosca template of the component {}. ",
- failedToAddRequirement.get().getName(), component.getName());
- result = Either.right(ToscaError.NODE_TYPE_CAPABILITY_ERROR);
- }
- logger.debug("Finish convert capalilities for the component {}. ", component.getName());
- }
- if(result == null){
- result = Either.left(toscaRequirements);
- }
- return result;
- }
-
- private boolean addEntry(Map<String,Component> componentsCache, Map<String, String[]> capReqMap, Component component, String name, String parentName, List<String> path){
-
- SubstituitionEntry entry = new SubstituitionEntry(name, parentName, "");
-
- if(shouldBuildSubstitutionName(component, path) && !buildSubstitutedNamePerInstance(componentsCache, component, name, path, entry)){
- return false;
- }
- logger.debug("The requirement/capability {} belongs to the component {} ", entry.getFullName(), component.getUniqueId());
- if (entry.getSourceName() != null) {
- addEntry(capReqMap, component, path, entry);
- }
- logger.debug("Finish convert the requirement/capability {} for the component {}. ", entry.getFullName(), component.getName());
- return true;
-
- }
-
- private boolean shouldBuildSubstitutionName(Component component, List<String> path) {
- return !ToscaUtils.isComplexVfc(component) && CollectionUtils.isNotEmpty(path) && path.iterator().hasNext();
- }
-
- private boolean buildSubstitutedNamePerInstance(Map<String, Component> componentsCache, Component component, String name, List<String> path, SubstituitionEntry entry) {
- Optional<ComponentInstance> ci = component.getComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst();
- if(ci.isPresent()){
- Either<String, Boolean> buildSubstitutedName = buildSubstitutedName(componentsCache, name, path, ci.get());
- if(buildSubstitutedName.isRight()){
- return false;
- }
- entry.setFullName(ci.get().getNormalizedName() + '.' + buildSubstitutedName.left().value());
- entry.setSourceName(buildSubstitutedName.left().value());
- } else {
- return false;
- }
- return true;
- }
-
- private void addEntry(Map<String, String[]> toscaRequirements, Component component, List<String> capPath, SubstituitionEntry entry) {
- Optional<ComponentInstance> findFirst = component.getComponentInstances().stream().filter(ci -> ci.getUniqueId().equals(Iterables.getLast(capPath))).findFirst();
- if (findFirst.isPresent()) {
- entry.setOwner(findFirst.get().getNormalizedName());
- }
- toscaRequirements.put(entry.getFullName(), new String[] { entry.getOwner(), entry.getSourceName() });
- }
-
- private Either<String, Boolean> buildSubstitutedName(Map<String, Component> componentsCache, String name, List<String> path, ComponentInstance instance) {
-
- Either<String, Boolean> result = null;
- Either<Component, Boolean> getOriginRes = getOriginComponent(componentsCache, instance);
- if(getOriginRes.isRight()){
- logger.debug("Failed to build substituted name for the capability/requirement {}. Failed to get an origin component with uniqueId {}", name, instance.getComponentUid());
- result = Either.right(false);
- }
- if(result == null){
- List<String> reducedPath = getReducedPath(path);
- reducedPath.remove(reducedPath.size()-1);
- result = buildSubstitutedName(componentsCache, getOriginRes.left().value(), reducedPath, name);
- }
- return result;
- }
-
- private String getRequirementPath(Component component, RequirementDefinition r) {
-
- // Evg : for the last in path take real instance name and not "decrypt" unique id. ( instance name can be change and not equal to id..)
- // dirty quick fix. must be changed as capability redesign
- List<String> capPath = r.getPath();
- String lastInPath = capPath.get(capPath.size() - 1);
- Optional<ComponentInstance> findFirst = component.getComponentInstances().stream().filter(ci -> ci.getUniqueId().equals(lastInPath)).findFirst();
- if (findFirst.isPresent()) {
- String lastInPathName = findFirst.get().getNormalizedName();
-
- if (capPath.size() > 1) {
- List<String> pathArray = Lists.reverse(capPath.stream().map(path -> ValidationUtils.normalizeComponentInstanceName(getSubPathByLastDelimiterAppearance(path))).collect(Collectors.toList()));
-
- return new StringBuilder().append(lastInPathName).append(PATH_DELIMITER).append(String.join(PATH_DELIMITER, pathArray.subList(1, pathArray.size() ))).append(PATH_DELIMITER).append(r.getName()).toString();
- }else{
- return new StringBuilder().append(lastInPathName).append(PATH_DELIMITER).append(r.getName()).toString();
- }
- }
- return "";
- }
-
- private ImmutablePair<String, ToscaRequirement> convertRequirement(Component component, boolean isNodeType, RequirementDefinition r) {
- String name = r.getName();
- if (!isNodeType) {
- name = getRequirementPath(component, r);
- }
- logger.debug("the requirement {} belongs to resource {} ", name, component.getUniqueId());
- ToscaRequirement toscaRequirement = new ToscaRequirement();
-
- List<Object> occurences = new ArrayList<>();
- occurences.add(Integer.valueOf(r.getMinOccurrences()));
- if (r.getMaxOccurrences().equals(RequirementDataDefinition.MAX_OCCURRENCES)) {
- occurences.add(r.getMaxOccurrences());
- } else {
- occurences.add(Integer.valueOf(r.getMaxOccurrences()));
- }
- toscaRequirement.setOccurrences(occurences);
- toscaRequirement.setNode(r.getNode());
- toscaRequirement.setCapability(r.getCapability());
- toscaRequirement.setRelationship(r.getRelationship());
-
- return new ImmutablePair<>(name, toscaRequirement);
- }
-
- /**
- * Allows to convert capabilities of a node type to tosca template capabilities
- * @param component
- * @param dataTypes
- * @return
- */
- public Map<String, ToscaCapability> convertCapabilities(Component component, Map<String, DataTypeDefinition> dataTypes) {
- Map<String, List<CapabilityDefinition>> capabilities = component.getCapabilities();
- Map<String, ToscaCapability> toscaCapabilities = new HashMap<>();
- if (capabilities != null) {
- boolean isNodeType = ModelConverter.isAtomicComponent(component);
- for (Map.Entry<String, List<CapabilityDefinition>> entry : capabilities.entrySet()) {
- entry.getValue().stream().filter(c -> filter(component, c.getOwnerId())).forEach(c -> convertCapabilty(component, toscaCapabilities, isNodeType, c, dataTypes));
- }
- } else {
- logger.debug(NO_CAPABILITIES);
- }
-
- return toscaCapabilities;
- }
-
- /**
- * Allows to convert capabilities of a server proxy node type to tosca template capabilities
- * @param component
- * @param proxyComponent
- * @param instanceProxy
- * @param dataTypes
- * @return
- */
- public Map<String, ToscaCapability> convertProxyCapabilities(Component component, Component proxyComponent, ComponentInstance instanceProxy, Map<String, DataTypeDefinition> dataTypes) {
- Map<String, List<CapabilityDefinition>> capabilities = instanceProxy.getCapabilities();
- Map<String, ToscaCapability> toscaCapabilities = new HashMap<>();
- if (capabilities != null) {
- boolean isNodeType = ModelConverter.isAtomicComponent(component);
- for (Map.Entry<String, List<CapabilityDefinition>> entry : capabilities.entrySet()) {
- entry.getValue().stream().forEach(c -> convertCapabilty(proxyComponent, toscaCapabilities, isNodeType, c, dataTypes));
- }
- } else {
- logger.debug(NO_CAPABILITIES);
- }
-
- return toscaCapabilities;
- }
-
- /**
- * Allows to convert component capabilities to the tosca template substitution mappings capabilities
- * @param componentsCache
- * @param component
- * @return
- */
- public Either<Map<String, String[]>, ToscaError> convertSubstitutionMappingCapabilities(Map<String, Component> componentsCache, Component component) {
- Map<String, List<CapabilityDefinition>> capabilities = component.getCapabilities();
- Either<Map<String, String[]>, ToscaError> res;
- if (capabilities != null) {
- res = buildAddSubstitutionMappingsCapabilities(componentsCache, component, capabilities);
- } else {
- res = Either.left(Maps.newHashMap());
- logger.debug(NO_CAPABILITIES);
- }
- return res;
- }
-
- private String getCapabilityPath(CapabilityDefinition c, Component component) {
- // Evg : for the last in path take real instance name and not "decrypt" unique id. ( instance name can be change and not equal to id..)
- // dirty quick fix. must be changed as capability redesign
- List<String> capPath = c.getPath();
- String lastInPath = capPath.get(capPath.size() - 1);
- Optional<ComponentInstance> findFirst = component.getComponentInstances().stream().filter(ci -> ci.getUniqueId().equals(lastInPath)).findFirst();
- if (findFirst.isPresent()) {
- String lastInPathName = findFirst.get().getNormalizedName();
-
- if (capPath.size() > 1) {
- List<String> pathArray = Lists.reverse(capPath.stream().map(path -> ValidationUtils.normalizeComponentInstanceName(getSubPathByLastDelimiterAppearance(path))).collect(Collectors.toList()));
-
- return new StringBuilder().append(lastInPathName).append(PATH_DELIMITER).append(String.join(PATH_DELIMITER, pathArray.subList(1, pathArray.size() ))).append(PATH_DELIMITER).append(c.getName()).toString();
- }else{
- return new StringBuilder().append(lastInPathName).append(PATH_DELIMITER).append(c.getName()).toString();
- }
- }
- return "";
- }
-
- private void convertCapabilty(Component component, Map<String, ToscaCapability> toscaCapabilities, boolean isNodeType, CapabilityDefinition c, Map<String, DataTypeDefinition> dataTypes) {
- String name = c.getName();
- if (!isNodeType) {
- name = getCapabilityPath(c, component);
- }
- logger.debug("the capabilty {} belongs to resource {} ", name, component.getUniqueId());
- ToscaCapability toscaCapability = new ToscaCapability();
- toscaCapability.setDescription(c.getDescription());
- toscaCapability.setType(c.getType());
-
- List<Object> occurences = new ArrayList<>();
- occurences.add(Integer.valueOf(c.getMinOccurrences()));
- if (c.getMaxOccurrences().equals(CapabilityDataDefinition.MAX_OCCURRENCES)) {
- occurences.add(c.getMaxOccurrences());
- } else {
- occurences.add(Integer.valueOf(c.getMaxOccurrences()));
- }
- toscaCapability.setOccurrences(occurences);
-
- toscaCapability.setValid_source_types(c.getValidSourceTypes());
- List<ComponentInstanceProperty> properties = c.getProperties();
- if (CollectionUtils.isNotEmpty(properties)) {
- Map<String, ToscaProperty> toscaProperties = new HashMap<>();
- for (PropertyDefinition property : properties) {
- ToscaProperty toscaProperty = PropertyConvertor.getInstance().convertProperty(dataTypes, property, true);
- toscaProperties.put(property.getName(), toscaProperty);
- }
- toscaCapability.setProperties(toscaProperties);
- }
- toscaCapabilities.put(name, toscaCapability);
- }
- /**
- * Allows to build substituted name of capability\requirement of the origin component instance according to the path
- * @param componentsCache
- * @param originComponent
- * @param path
- * @param name
- * @return
- */
- public Either<String, Boolean> buildSubstitutedName(Map<String, Component> componentsCache, Component originComponent, List<String> path, String name) {
- StringBuilder substitutedName = new StringBuilder();
- boolean nameBuiltSuccessfully = true;
- Either<String, Boolean> result;
- if(CollectionUtils.isNotEmpty(path) && !ToscaUtils.isComplexVfc(originComponent)){
- List<String> reducedPath = getReducedPath(path);
- Collections.reverse(reducedPath);
- nameBuiltSuccessfully = appendNameRecursively(componentsCache, originComponent, reducedPath.iterator(), substitutedName);
- }
- if(nameBuiltSuccessfully){
- result = Either.left(substitutedName.append(name).toString());
- } else {
- result = Either.right(nameBuiltSuccessfully);
- }
- return result;
- }
-
- private List<String> getReducedPath(List<String> path) {
- List<String> pathCopy = Lists.newArrayList();
- path.stream().forEach(id -> {if(!pathCopy.contains(id))pathCopy.add(id);});
- return pathCopy;
- }
-
- private boolean appendNameRecursively(Map<String, Component> componentsCache, Component originComponent, Iterator<String> instanceIdIter, StringBuilder substitutedName) {
- if(CollectionUtils.isNotEmpty(originComponent.getComponentInstances()) && instanceIdIter.hasNext() && !ToscaUtils.isComplexVfc(originComponent)){
- String instanceId = instanceIdIter.next();
- Optional<ComponentInstance> instanceOpt = originComponent.getComponentInstances().stream().filter(i -> i.getUniqueId().equals(instanceId)).findFirst();
- if(!instanceOpt.isPresent()){
- logger.debug("Failed to find an instance with uniqueId {} on a component with uniqueId {}", instanceId, originComponent.getUniqueId());
- return false;
- }
- substitutedName.append(instanceOpt.get().getNormalizedName()).append('.');
- Either<Component, Boolean> getOriginRes = getOriginComponent(componentsCache, instanceOpt.get());
- if(getOriginRes.isRight()){
- return false;
- }
- appendNameRecursively(componentsCache, getOriginRes.left().value(), instanceIdIter, substitutedName);
- }
- return true;
- }
-
- Either<Component, Boolean> getOriginComponent(Map<String, Component> componentsCache, ComponentInstance instance) {
- Either<Component, Boolean> result;
- Either<Component, StorageOperationStatus> getOriginRes;
- if(componentsCache.containsKey(instance.getActualComponentUid())){
- result = Either.left(componentsCache.get(instance.getActualComponentUid()));
- } else {
- ComponentParametersView filter = getFilter(instance);
- getOriginRes = toscaOperationFacade.getToscaElement(instance.getActualComponentUid(), filter);
- if(getOriginRes.isRight()){
- logger.debug("Failed to get an origin component with uniqueId {}", instance.getActualComponentUid());
- result = Either.right(false);
- } else {
- result = Either.left(getOriginRes.left().value());
- componentsCache.put(getOriginRes.left().value().getUniqueId(), getOriginRes.left().value());
- }
- }
- return result;
- }
-
- private ComponentParametersView getFilter(ComponentInstance instance) {
- ComponentParametersView filter = new ComponentParametersView(true);
- filter.setIgnoreComponentInstances(false);
- if(instance.getIsProxy()){
- filter.setIgnoreCapabilities(false);
- filter.setIgnoreRequirements(false);
- }
- return filter;
- }
-
-}
+
+ private static final String NO_CAPABILITIES = "No Capabilities for node type";
+ private static CapabiltyRequirementConvertor instance;
+ private static final Logger logger = LoggerFactory.getLogger(CapabiltyRequirementConvertor.class);
+ public static final String PATH_DELIMITER = ".";
+
+ @Autowired
+ private ToscaOperationFacade toscaOperationFacade;
+
+ protected CapabiltyRequirementConvertor() {}
+
+ public static synchronized CapabiltyRequirementConvertor getInstance() {
+ if (instance == null) {
+ instance = new CapabiltyRequirementConvertor();
+ }
+ return instance;
+ }
+
+ public String buildCapabilityNameForComponentInstance( Map<String,Component> componentCache , ComponentInstance componentInstance, CapabilityDefinition c) {
+
+ Either eitherName = buildSubstitutedName(componentCache, c.getName(), c.getPath(), c.getOwnerId(), componentInstance);
+
+ return eitherName.isLeft() ? (String) eitherName.left().value() : c.getName() ;
+ }
+
+
+ /**
+ * Allows to convert capabilities of a component to capabilities of a substitution mappings section of a tosca template
+ * @param componentInstance
+ * @param dataTypes
+ * @param nodeTemplate
+ * @return
+ */
+ public Either<ToscaNodeTemplate, ToscaError> convertComponentInstanceCapabilties(ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, ToscaNodeTemplate nodeTemplate) {
+
+ Map<String, List<CapabilityDefinition>> capabilitiesInst = componentInstance.getCapabilities();
+ Map<String,Component> componentCache = new HashMap<>();
+ if (capabilitiesInst != null && !capabilitiesInst.isEmpty()) {
+ Map<String, ToscaTemplateCapability> capabilities = new HashMap<>();
+ capabilitiesInst.entrySet().forEach( e -> {
+ List<CapabilityDefinition> capList = e.getValue();
+ if ( capList != null && !capList.isEmpty() ) {
+ capList.forEach( c -> {
+ String capName = buildCapabilityNameForComponentInstance( componentCache , componentInstance , c ) ;
+ convertOverridenProperties( componentInstance, dataTypes, capabilities, c , capName );
+ } );
+ }
+ });
+ if (MapUtils.isNotEmpty(capabilities)) {
+ nodeTemplate.setCapabilities(capabilities);
+ }
+ }
+ return Either.left(nodeTemplate);
+ }
+
+ private void convertOverridenProperties(ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, Map<String, ToscaTemplateCapability> capabilties, CapabilityDefinition c , String capabilityName) {
+ if (isNotEmpty(c.getProperties())) {
+ c.getProperties()
+ .stream()
+ .filter(p -> p.getValue() != null || p.getDefaultValue() != null)
+ .forEach(p -> convertOverridenProperty(componentInstance, dataTypes, capabilties , p ,capabilityName));
+ }
+ }
+
+ private void convertOverridenProperty(ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, Map<String, ToscaTemplateCapability> capabilties, ComponentInstanceProperty p ,String capabilityName) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Exist overriden property {} for capabity {} with value {}", p.getName(), capabilityName, p.getValue());
+ }
+ ToscaTemplateCapability toscaTemplateCapability = capabilties.computeIfAbsent( capabilityName , key -> new ToscaTemplateCapability() );
+
+ Map<String, Object> toscaCapProp = toscaTemplateCapability.getProperties();
+ if (toscaCapProp == null) {
+ toscaCapProp = new HashMap<>();
+ }
+ Object convertedValue = convertInstanceProperty(dataTypes, componentInstance, p);
+ toscaCapProp.put(p.getName(), convertedValue);
+ toscaTemplateCapability.setProperties(toscaCapProp);
+ }
+
+ private Object convertInstanceProperty(Map<String, DataTypeDefinition> dataTypes, ComponentInstance componentInstance, ComponentInstanceProperty prop) {
+ logger.debug("Convert property {} for instance {}", prop.getName(), componentInstance.getUniqueId());
+ String propertyType = prop.getType();
+ String innerType = null;
+ if (prop.getSchema() != null && prop.getSchema().getProperty() != null) {
+ innerType = prop.getSchema().getProperty().getType();
+ }
+ String propValue = prop.getValue() == null ? prop.getDefaultValue() : prop.getValue();
+ return PropertyConvertor.getInstance().convertToToscaObject(propertyType, propValue, innerType, dataTypes);
+ }
+ /**
+ * Allows to convert requirements of a node type to tosca template requirements representation
+ * @param component
+ * @param nodeType
+ * @return
+ */
+ public Either<ToscaNodeType, ToscaError> convertRequirements(Component component, ToscaNodeType nodeType) {
+ List<Map<String, ToscaRequirement>> toscaRequirements = convertRequirementsAsList(component);
+ if (!toscaRequirements.isEmpty()) {
+ nodeType.setRequirements(toscaRequirements);
+ }
+ logger.debug("Finish convert Requirements for node type");
+
+ return Either.left(nodeType);
+ }
+
+ /**
+ * Allows to convert component requirements to the tosca template substitution mappings requirements
+ * @param componentsCache
+ * @param component
+ * @param substitutionMappings
+ * @return
+ */
+ public Either<SubstitutionMapping, ToscaError> convertSubstitutionMappingRequirements(Map<String,Component> componentsCache, Component component, SubstitutionMapping substitutionMappings) {
+ Either<SubstitutionMapping, ToscaError> result = Either.left(substitutionMappings);
+ Either<Map<String, String[]>, ToscaError> toscaRequirementsRes = convertSubstitutionMappingRequirementsAsMap(componentsCache, component);
+ if(toscaRequirementsRes.isRight()){
+ result = Either.right(toscaRequirementsRes.right().value());
+ logger.error("Failed convert requirements for the component {}. ", component.getName());
+ } else if (MapUtils.isNotEmpty(toscaRequirementsRes.left().value())) {
+ substitutionMappings.setRequirements(toscaRequirementsRes.left().value());
+ result = Either.left(substitutionMappings);
+ logger.debug("Finish convert requirements for the component {}. ", component.getName());
+ }
+ return result;
+ }
+
+ private List<Map<String, ToscaRequirement>> convertRequirementsAsList(Component component) {
+ Map<String, List<RequirementDefinition>> requirements = component.getRequirements();
+ List<Map<String, ToscaRequirement>> toscaRequirements = new ArrayList<>();
+ if (requirements != null) {
+ for (Map.Entry<String, List<RequirementDefinition>> entry : requirements.entrySet()) {
+ entry.getValue().stream().filter(r -> filter(component, r.getOwnerId())).forEach(r -> {
+ ImmutablePair<String, ToscaRequirement> pair = convertRequirement(component, ModelConverter.isAtomicComponent(component), r);
+ Map<String, ToscaRequirement> requirement = new HashMap<>();
+
+ requirement.put(pair.left, pair.right);
+ toscaRequirements.add(requirement);
+ });
+ logger.debug("Finish convert Requirements for node type");
+ }
+ } else {
+ logger.debug("No Requirements for node type");
+ }
+ return toscaRequirements;
+ }
+
+ private boolean filter(Component component, String ownerId) {
+ return !ModelConverter.isAtomicComponent(component) || isNodeTypeOwner(component, ownerId) || (ModelConverter.isAtomicComponent(component) && ownerId == null);
+ }
+
+ private boolean isNodeTypeOwner(Component component, String ownerId) {
+ return ModelConverter.isAtomicComponent(component) && component.getUniqueId().equals(ownerId);
+ }
+
+ private String getSubPathByLastDelimiterAppearance(String path) {
+ return path.substring(path.lastIndexOf(PATH_DELIMITER) + 1);
+ }
+
+ private String dropLast( String path, String delimiter ) {
+ if (isBlank(path) || isBlank(delimiter)){
+ return path;
+ }
+ return path.substring(0, path.lastIndexOf(delimiter));
+ }
+
+ private Either<Map<String, String[]>, ToscaError> convertSubstitutionMappingRequirementsAsMap(Map<String, Component> componentsCache, Component component) {
+ Map<String, List<RequirementDefinition>> requirements = component.getRequirements();
+ Either<Map<String, String[]>, ToscaError> result;
+ if (requirements != null) {
+ result = buildAddSubstitutionMappingsRequirements(componentsCache, component, requirements);
+ } else {
+ result = Either.left(Maps.newHashMap());
+ logger.debug("No requirements for substitution mappings section of a tosca template of the component {}. ", component.getName());
+ }
+ return result;
+ }
+
+ private Either<Map<String, String[]>, ToscaError> buildAddSubstitutionMappingsRequirements(Map<String, Component> componentsCache, Component component, Map<String, List<RequirementDefinition>> requirements) {
+
+ Map<String, String[]> toscaRequirements = new HashMap<>();
+ Either<Map<String, String[]>, ToscaError> result = null;
+ for (Map.Entry<String, List<RequirementDefinition>> entry : requirements.entrySet()) {
+ Optional<RequirementDefinition> failedToAddRequirement = entry.getValue()
+ .stream()
+ .filter(r->!addEntry(componentsCache, toscaRequirements, component, r.getName(), r.getParentName(), r.getOwnerId(), r.getPath()))
+ .findAny();
+ if(failedToAddRequirement.isPresent()){
+ logger.error("Failed to convert requirement {} for substitution mappings section of a tosca template of the component {}. ",
+ failedToAddRequirement.get().getName(), component.getName());
+ result = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR);
+ }
+ logger.debug("Finish convert requirements for the component {}. ", component.getName());
+ }
+ if(result == null){
+ result = Either.left(toscaRequirements);
+ }
+ return result;
+ }
+
+ private Either<Map<String, String[]>, ToscaError> buildAddSubstitutionMappingsCapabilities(Map<String, Component> componentsCache, Component component, Map<String, List<CapabilityDefinition>> capabilities) {
+
+ Map<String, String[]> toscaRequirements = new HashMap<>();
+ Either<Map<String, String[]>, ToscaError> result = null;
+ for (Map.Entry<String, List<CapabilityDefinition>> entry : capabilities.entrySet()) {
+ Optional<CapabilityDefinition> failedToAddRequirement = entry.getValue()
+ .stream()
+ .filter(c->!addEntry(componentsCache, toscaRequirements, component, c.getName(), c.getParentName(), c.getOwnerId(), c.getPath()))
+ .findAny();
+ if(failedToAddRequirement.isPresent()){
+ logger.error("Failed to convert capalility {} for substitution mappings section of a tosca template of the component {}. ",
+ failedToAddRequirement.get().getName(), component.getName());
+ result = Either.right(ToscaError.NODE_TYPE_CAPABILITY_ERROR);
+ }
+ logger.debug("Finish convert capalilities for the component {}. ", component.getName());
+ }
+ if(result == null){
+ result = Either.left(toscaRequirements);
+ }
+ return result;
+ }
+
+ private boolean addEntry(Map<String,Component> componentsCache, Map<String, String[]> capReqMap, Component component, String name, String parentName, String ownerId, List<String> path){
+
+ SubstituitionEntry entry = new SubstituitionEntry(name, parentName, "");
+
+ if(shouldBuildSubstitutionName(component, path) && !buildSubstitutedNamePerInstance(componentsCache, component, name, path, ownerId, entry)){
+ return false;
+ }
+ logger.debug("The requirement/capability {} belongs to the component {} ", entry.getFullName(), component.getUniqueId());
+ if (entry.getSourceName() != null) {
+ addEntry(capReqMap, component, path, entry);
+ }
+ logger.debug("Finish convert the requirement/capability {} for the component {}. ", entry.getFullName(), component.getName());
+ return true;
+
+ }
+
+ private boolean shouldBuildSubstitutionName(Component component, List<String> path) {
+ return !ToscaUtils.isComplexVfc(component) && isNotEmpty(path) && path.iterator().hasNext();
+ }
+
+ private boolean buildSubstitutedNamePerInstance(Map<String, Component> componentsCache, Component component, String name, List<String> path, String ownerId, SubstituitionEntry entry) {
+ Optional<ComponentInstance> ci = component.getComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst();
+ if(!ci.isPresent()){
+ logger.error("Failed to find ci in the path is {} component {}", path, component.getUniqueId());
+
+ Collections.reverse(path);
+
+ logger.error("try to reverse path {} component {}", path, component.getUniqueId());
+ ci = component.getComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst();
+ }
+ if(ci.isPresent()){
+ Either<String, Boolean> buildSubstitutedName = buildSubstitutedName(componentsCache, name, path, ownerId, ci.get());
+ if(buildSubstitutedName.isRight()){
+ logger.error("Failed buildSubstitutedName name {} path {} component {}", name, path, component.getUniqueId());
+ return false;
+ }
+ entry.setFullName(ci.get().getNormalizedName() + '.' + buildSubstitutedName.left().value());
+ entry.setSourceName(buildSubstitutedName.left().value());
+ } else {
+ logger.error("Failed to find ci in the path is {} component {}", path, component.getUniqueId());
+ return false;
+ }
+ return true;
+ }
+
+ private void addEntry(Map<String, String[]> toscaRequirements, Component component, List<String> capPath, SubstituitionEntry entry) {
+ Optional<ComponentInstance> findFirst = component.getComponentInstances().stream().filter(ci -> ci.getUniqueId().equals(Iterables.getLast(capPath))).findFirst();
+ if (findFirst.isPresent()) {
+ entry.setOwner(findFirst.get().getNormalizedName());
+ }
+ toscaRequirements.put(entry.getFullName(), new String[] { entry.getOwner(), entry.getSourceName() });
+ }
+
+ public Either<String, Boolean> buildSubstitutedName(Map<String, Component> componentsCache, String name, List<String> path, String ownerId, ComponentInstance instance) {
+
+ Either<String, Boolean> result = null;
+ Either<Component, Boolean> getOriginRes = getOriginComponent(componentsCache, instance);
+ if(getOriginRes.isRight()){
+ logger.error("Failed to build substituted name for the capability/requirement {}. Failed to get an origin component with uniqueId {}", name, instance.getComponentUid());
+ result = Either.right(false);
+ }
+ if(result == null){
+ List<String> reducedPath = ownerId !=null ? getReducedPathByOwner(path , ownerId ) : getReducedPath(path) ;
+ logger.debug("reducedPath for ownerId {}, reducedPath {} ", ownerId, reducedPath);
+ reducedPath.remove(reducedPath.size()-1);
+ result = buildSubstitutedName(componentsCache, getOriginRes.left().value(), reducedPath, name);
+ }
+ return result;
+ }
+
+ private String getRequirementPath(Component component, RequirementDefinition r) {
+
+ // Evg : for the last in path take real instance name and not "decrypt" unique id. ( instance name can be change and not equal to id..)
+ // dirty quick fix. must be changed as capability redesign
+ List<String> capPath = r.getPath();
+ String lastInPath = capPath.get(capPath.size() - 1);
+ Optional<ComponentInstance> findFirst = component.getComponentInstances().stream().filter(ci -> ci.getUniqueId().equals(lastInPath)).findFirst();
+ if (findFirst.isPresent()) {
+ String lastInPathName = findFirst.get().getNormalizedName();
+
+ if (capPath.size() > 1) {
+ List<String> pathArray = Lists.reverse(capPath.stream().map(path -> ValidationUtils.normalizeComponentInstanceName(getSubPathByLastDelimiterAppearance(path))).collect(Collectors.toList()));
+
+ return new StringBuilder().append(lastInPathName).append(PATH_DELIMITER).append(String.join(PATH_DELIMITER, pathArray.subList(1, pathArray.size() ))).append(PATH_DELIMITER).append(r.getName()).toString();
+ }else{
+ return new StringBuilder().append(lastInPathName).append(PATH_DELIMITER).append(r.getName()).toString();
+ }
+ }
+ return "";
+ }
+
+ private ImmutablePair<String, ToscaRequirement> convertRequirement(Component component, boolean isNodeType, RequirementDefinition r) {
+ String name = r.getName();
+ if (!isNodeType) {
+ name = getRequirementPath(component, r);
+ }
+ logger.debug("the requirement {} belongs to resource {} ", name, component.getUniqueId());
+ ToscaRequirement toscaRequirement = new ToscaRequirement();
+
+ List<Object> occurences = new ArrayList<>();
+ occurences.add(Integer.valueOf(r.getMinOccurrences()));
+ if (r.getMaxOccurrences().equals(RequirementDataDefinition.MAX_OCCURRENCES)) {
+ occurences.add(r.getMaxOccurrences());
+ } else {
+ occurences.add(Integer.valueOf(r.getMaxOccurrences()));
+ }
+ toscaRequirement.setOccurrences(occurences);
+ toscaRequirement.setNode(r.getNode());
+ toscaRequirement.setCapability(r.getCapability());
+ toscaRequirement.setRelationship(r.getRelationship());
+
+ return new ImmutablePair<>(name, toscaRequirement);
+ }
+
+ /**
+ * Allows to convert capabilities of a node type to tosca template capabilities
+ * @param component
+ * @param dataTypes
+ * @return
+ */
+ public Map<String, ToscaCapability> convertCapabilities(Component component, Map<String, DataTypeDefinition> dataTypes) {
+ Map<String, List<CapabilityDefinition>> capabilities = component.getCapabilities();
+ Map<String, ToscaCapability> toscaCapabilities = new HashMap<>();
+ if (capabilities != null) {
+ boolean isNodeType = ModelConverter.isAtomicComponent(component);
+ for (Map.Entry<String, List<CapabilityDefinition>> entry : capabilities.entrySet()) {
+ entry.getValue().stream().filter(c -> filter(component, c.getOwnerId())).forEach(c -> convertCapabilty(component, toscaCapabilities, isNodeType, c, dataTypes , c.getName()));
+ }
+ } else {
+ logger.debug(NO_CAPABILITIES);
+ }
+
+ return toscaCapabilities;
+ }
+
+ /**
+ * Allows to convert capabilities of a server proxy node type to tosca template capabilities
+ * @param component
+ * @param proxyComponent
+ * @param instanceProxy
+ * @param dataTypes
+ * @return
+ */
+ public Map<String, ToscaCapability> convertProxyCapabilities(Map<String, Component> componentCache, Component component, Component proxyComponent, ComponentInstance instanceProxy, Map<String, DataTypeDefinition> dataTypes) {
+ Map<String, List<CapabilityDefinition>> capabilities = instanceProxy.getCapabilities();
+ Map<String, ToscaCapability> toscaCapabilities = new HashMap<>();
+ if (capabilities != null) {
+ boolean isNodeType = ModelConverter.isAtomicComponent(component);
+ for (Map.Entry<String, List<CapabilityDefinition>> entry : capabilities.entrySet()) {
+ entry.getValue().stream().forEach(c -> convertCapabilty(proxyComponent, toscaCapabilities, isNodeType, c, dataTypes , buildCapabilityNameForComponentInstance( componentCache , instanceProxy , c )));
+ }
+ } else {
+ logger.debug(NO_CAPABILITIES);
+ }
+
+ return toscaCapabilities;
+ }
+
+ /**
+ * Allows to convert component capabilities to the tosca template substitution mappings capabilities
+ * @param componentsCache
+ * @param component
+ * @return
+ */
+ public Either<Map<String, String[]>, ToscaError> convertSubstitutionMappingCapabilities(Map<String, Component> componentsCache, Component component) {
+ Map<String, List<CapabilityDefinition>> capabilities = component.getCapabilities();
+ Either<Map<String, String[]>, ToscaError> res;
+ if (capabilities != null) {
+ res = buildAddSubstitutionMappingsCapabilities(componentsCache, component, capabilities);
+ } else {
+ res = Either.left(Maps.newHashMap());
+ logger.debug(NO_CAPABILITIES);
+ }
+ return res;
+ }
+
+ private String getCapabilityPath(CapabilityDefinition c, Component component) {
+ // Evg : for the last in path take real instance name and not "decrypt" unique id. ( instance name can be change and not equal to id..)
+ // dirty quick fix. must be changed as capability redesign
+ List<String> capPath = c.getPath();
+ String lastInPath = capPath.get(capPath.size() - 1);
+ Optional<ComponentInstance> findFirst = component.getComponentInstances().stream().filter(ci -> ci.getUniqueId().equals(lastInPath)).findFirst();
+ if (findFirst.isPresent()) {
+ String lastInPathName = findFirst.get().getNormalizedName();
+
+ if (capPath.size() > 1) {
+ List<String> pathArray = Lists.reverse(capPath.stream().map(path -> ValidationUtils.normalizeComponentInstanceName(getSubPathByLastDelimiterAppearance(path))).collect(Collectors.toList()));
+
+ return new StringBuilder().append(lastInPathName).append(PATH_DELIMITER).append(String.join(PATH_DELIMITER, pathArray.subList(1, pathArray.size() ))).append(PATH_DELIMITER).append(c.getName()).toString();
+ }else{
+ return new StringBuilder().append(lastInPathName).append(PATH_DELIMITER).append(c.getName()).toString();
+ }
+ }
+ return "";
+ }
+
+ private void convertCapabilty(Component component, Map<String, ToscaCapability> toscaCapabilities, boolean isNodeType, CapabilityDefinition c, Map<String, DataTypeDefinition> dataTypes , String capabilityName) {
+ String name = isNoneBlank(capabilityName) ? capabilityName : c.getName();
+ if (!isNodeType) {
+ name = getCapabilityPath(c, component);
+ }
+ logger.debug("the capabilty {} belongs to resource {} ", name, component.getUniqueId());
+ ToscaCapability toscaCapability = new ToscaCapability();
+ toscaCapability.setDescription(c.getDescription());
+ toscaCapability.setType(c.getType());
+
+ List<Object> occurences = new ArrayList<>();
+ occurences.add(Integer.valueOf(c.getMinOccurrences()));
+ if (c.getMaxOccurrences().equals(CapabilityDataDefinition.MAX_OCCURRENCES)) {
+ occurences.add(c.getMaxOccurrences());
+ } else {
+ occurences.add(Integer.valueOf(c.getMaxOccurrences()));
+ }
+ toscaCapability.setOccurrences(occurences);
+
+ toscaCapability.setValid_source_types(c.getValidSourceTypes());
+ List<ComponentInstanceProperty> properties = c.getProperties();
+ if (isNotEmpty(properties)) {
+ Map<String, ToscaProperty> toscaProperties = new HashMap<>();
+ for (PropertyDefinition property : properties) {
+ ToscaProperty toscaProperty = PropertyConvertor.getInstance().convertProperty(dataTypes, property, true);
+ toscaProperties.put(property.getName(), toscaProperty);
+ }
+ toscaCapability.setProperties(toscaProperties);
+ }
+ toscaCapabilities.put(name, toscaCapability);
+ }
+ /**
+ * Allows to build substituted name of capability\requirement of the origin component instance according to the path
+ * @param componentsCache
+ * @param originComponent
+ * @param path
+ * @param name
+ * @return
+ */
+ public Either<String, Boolean> buildSubstitutedName(Map<String, Component> componentsCache, Component originComponent, List<String> path, String name) {
+ StringBuilder substitutedName = new StringBuilder();
+ boolean nameBuiltSuccessfully = true;
+ Either<String, Boolean> result;
+ if(isNotEmpty(path) && !ToscaUtils.isComplexVfc(originComponent)){
+ List<String> reducedPath = getReducedPath(path);
+ Collections.reverse(reducedPath);
+ nameBuiltSuccessfully = appendNameRecursively(componentsCache, originComponent, reducedPath.iterator(), substitutedName);
+ }
+ if(nameBuiltSuccessfully){
+ result = Either.left(substitutedName.append(name).toString());
+ } else {
+ result = Either.right(nameBuiltSuccessfully);
+ }
+ return result;
+ }
+
+ protected List<String> getReducedPathByOwner(List<String> path , String ownerId) {
+ logger.debug("ownerId {}, path {} ", ownerId, path);
+ if ( CollectionUtils.isEmpty(path) ){
+ logger.debug("cannot perform reduce by owner, path to component is empty");
+ return path;
+ }
+ if ( isBlank(ownerId) ){
+ logger.debug("cannot perform reduce by owner, component owner is empty");
+ return path;
+ }
+ //reduce by owner
+ Map map = path.stream().collect( Collectors.toMap( it -> dropLast(it,PATH_DELIMITER) , Function.identity() , ( a , b ) -> a.endsWith(ownerId) ? a : b ));
+ //reduce list&duplicates and preserve order
+ return path.stream().distinct().filter(it -> map.values().contains(it) ).collect(Collectors.toList());
+ }
+
+ private List<String> getReducedPath(List<String> path) {
+ return path.stream().distinct().collect(Collectors.toList());
+ }
+
+ private boolean appendNameRecursively(Map<String, Component> componentsCache, Component originComponent, Iterator<String> instanceIdIter, StringBuilder substitutedName) {
+ if(isNotEmpty(originComponent.getComponentInstances()) && instanceIdIter.hasNext() && !ToscaUtils.isComplexVfc(originComponent)){
+ String instanceId = instanceIdIter.next();
+ Optional<ComponentInstance> instanceOpt = originComponent.getComponentInstances().stream().filter(i -> i.getUniqueId().equals(instanceId)).findFirst();
+ if(!instanceOpt.isPresent()){
+ logger.error("Failed to find an instance with uniqueId {} on a component with uniqueId {}", instanceId, originComponent.getUniqueId());
+ return false;
+ }
+ substitutedName.append(instanceOpt.get().getNormalizedName()).append('.');
+ Either<Component, Boolean> getOriginRes = getOriginComponent(componentsCache, instanceOpt.get());
+ if(getOriginRes.isRight()){
+ return false;
+ }
+ appendNameRecursively(componentsCache, getOriginRes.left().value(), instanceIdIter, substitutedName);
+ }
+ return true;
+ }
+
+ Either<Component, Boolean> getOriginComponent(Map<String, Component> componentsCache, ComponentInstance instance) {
+ Either<Component, Boolean> result;
+ Either<Component, StorageOperationStatus> getOriginRes;
+ if(componentsCache.containsKey(instance.getActualComponentUid())){
+ result = Either.left(componentsCache.get(instance.getActualComponentUid()));
+ } else {
+ ComponentParametersView filter = getFilter(instance);
+ getOriginRes = toscaOperationFacade.getToscaElement(instance.getActualComponentUid(), filter);
+ if(getOriginRes.isRight()){
+ logger.error("Failed to get an origin component with uniqueId {}", instance.getActualComponentUid());
+ result = Either.right(false);
+ } else {
+ result = Either.left(getOriginRes.left().value());
+ componentsCache.put(getOriginRes.left().value().getUniqueId(), getOriginRes.left().value());
+ }
+ }
+ return result;
+ }
+
+ private ComponentParametersView getFilter(ComponentInstance instance) {
+ ComponentParametersView filter = new ComponentParametersView(true);
+ filter.setIgnoreComponentInstances(false);
+ if(instance.getIsProxy()){
+ filter.setIgnoreCapabilities(false);
+ filter.setIgnoreRequirements(false);
+ filter.setIgnoreCategories(false);
+ }
+ return filter;
+ }
+
+} \ No newline at end of file