fix capabilities
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / tosca / CapabiltyRequirementConvertor.java
index 649f083..0c93ee8 100644 (file)
@@ -1,5 +1,4 @@
 /*-
-
  * ============LICENSE_START=======================================================
  * SDC
  * ================================================================================
 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 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;
@@ -34,9 +38,14 @@ 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.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;
@@ -47,14 +56,29 @@ import org.openecomp.sdc.be.tosca.model.ToscaTemplateCapability;
 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 fj.data.Either;
-
+/**
+ * Allows to convert requirements\capabilities of a component to requirements\capabilities of a substitution mappings section of a tosca template
+ *
+ */
+@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;
-       public final static String PATH_DELIMITER = ".";
+       private static Logger logger = LoggerFactory.getLogger(CapabiltyRequirementConvertor.class.getName());
+       public static final String PATH_DELIMITER = ".";
+       
+       @Autowired
+       private ToscaOperationFacade toscaOperationFacade;
        
        protected CapabiltyRequirementConvertor() {
 
@@ -66,9 +90,13 @@ public class CapabiltyRequirementConvertor {
                }
                return instance;
        }
-
-       private static Logger log = LoggerFactory.getLogger(CapabiltyRequirementConvertor.class.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();
@@ -77,12 +105,10 @@ public class CapabiltyRequirementConvertor {
                        capabilitiesInst.entrySet().forEach(e -> {
                                List<CapabilityDefinition> capList = e.getValue();
                                if (capList != null && !capList.isEmpty()) {
-                                       capList.forEach(c -> {
-                                               convertOverridenProperties(componentInstance, dataTypes, capabilties, c);
-                                       });
+                                       capList.forEach(c -> convertOverridenProperties(componentInstance, dataTypes, capabilties, c));
                                }
                        });
-                       if (capabilties != null && !capabilties.isEmpty()) {
+                       if (MapUtils.isNotEmpty(capabilties)) {
                                nodeTemplate.setCapabilities(capabilties);
                        }
                }
@@ -92,15 +118,16 @@ public class CapabiltyRequirementConvertor {
        private void convertOverridenProperties(ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, Map<String, ToscaTemplateCapability> capabilties, CapabilityDefinition c) {
                List<ComponentInstanceProperty> properties = c.getProperties();
                if (properties != null && !properties.isEmpty()) {
-                       properties.stream().filter(p -> (p.getValueUniqueUid() != null)).forEach(p -> {
-                               convertOverridenProperty(componentInstance, dataTypes, capabilties, c, p);
-                       });
+                       properties
+                       .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 (log.isDebugEnabled()) {
-                       log.debug("Exist overriden property {} for capabity {} with value {}", p.getName(), c.getName(), p.getValue());
+               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) {
@@ -117,109 +144,224 @@ public class CapabiltyRequirementConvertor {
        }
 
        private Object convertInstanceProperty(Map<String, DataTypeDefinition> dataTypes, ComponentInstance componentInstance, ComponentInstanceProperty prop) {
-               log.debug("Convert property {} for instance {}", prop.getName(), componentInstance.getUniqueId());
+               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();
                }
-               Object convertedValue = PropertyConvertor.getInstance().convertToToscaObject(propertyType,  prop.getValue(), innerType, dataTypes);
-               return convertedValue;
+               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);
                }
-               log.debug("Finish convert Requirements for node type");
+               logger.debug("Finish convert Requirements for node type");
 
                return Either.left(nodeType);
        }
 
-       public Either<SubstitutionMapping, ToscaError> convertSubstitutionMappingRequirements(Component component, SubstitutionMapping substitutionMapping) {
-               Map<String, String[]> toscaRequirements = convertSubstitutionMappingRequirementsAsMap(component);
-               if (!toscaRequirements.isEmpty()) {
-                       substitutionMapping.setRequirements(toscaRequirements);
+       /**
+        * 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());
                }
-               log.debug("Finish convert Requirements for node type");
-
-               return Either.left(substitutionMapping);
+               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) {
-                       boolean isNodeType = ToscaUtils.isAtomicType(component);
                        for (Map.Entry<String, List<RequirementDefinition>> entry : requirements.entrySet()) {
-                               entry.getValue().stream().filter(r -> (!isNodeType || (isNodeType && component.getUniqueId().equals(r.getOwnerId())) || (isNodeType && r.getOwnerId() == null))).forEach(r -> {
-                                       ImmutablePair<String, ToscaRequirement> pair = convertRequirement(component, isNodeType, r);
+                               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);
                                });
-
-                               log.debug("Finish convert Requirements for node type");
+                               logger.debug("Finish convert Requirements for node type");
                        }
                } else {
-                       log.debug("No Requirements for node type");
+                       logger.debug("No Requirements for node type");
                }
                return toscaRequirements;
        }
 
-       private String getSubPathByFirstDelimiterAppearance(String path) {
-               return path.substring(path.indexOf(PATH_DELIMITER) + 1);
+       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);
        }
-       
-       //This function calls on Substitution Mapping region - the component is always non-atomic
-       private Map<String, String[]> convertSubstitutionMappingRequirementsAsMap(Component component) {
+
+       private Either<Map<String, String[]>, ToscaError> convertSubstitutionMappingRequirementsAsMap(Map<String, Component> componentsCache, Component component) {
                Map<String, List<RequirementDefinition>> requirements = component.getRequirements();
-               Map<String,  String[]> toscaRequirements = new HashMap<>();
+               Either<Map<String, String[]>, ToscaError> result;
                if (requirements != null) {
-                       for (Map.Entry<String, List<RequirementDefinition>> entry : requirements.entrySet()) {
-                               entry.getValue().stream().forEach(r -> {
-                                       String fullReqName;
-                                       String sourceCapName;
-                                       if(ToscaUtils.isComplexVfc(component)){
-                                               fullReqName = r.getName();
-                                               sourceCapName = r.getParentName();
-                                       } else {
-                                               fullReqName = getRequirementPath(r);
-                                               sourceCapName = getSubPathByFirstDelimiterAppearance(fullReqName);
-                                       }
-                                       log.debug("the requirement {} belongs to resource {} ", fullReqName, component.getUniqueId());
-                                       if(sourceCapName!= null){
-                                               toscaRequirements.put(fullReqName, new String[]{r.getOwnerName(), sourceCapName});
-                                       }
-                               });
-                               log.debug("Finish convert Requirements for node type");
-                       }
+                       result = buildAddSubstitutionMappingsRequirements(componentsCache, component, requirements);
                } else {
-                       log.debug("No Requirements for node type");
+                       result = Either.left(Maps.newHashMap());
+                       logger.debug("No requirements for substitution mappings section of a tosca template of the component {}. ", component.getName());
                }
-               return toscaRequirements;
+               return result;
        }
 
-       private String getRequirementPath(RequirementDefinition r) {
-               List<String> pathArray = Lists.reverse(r.getPath().stream()
-                               .map(path -> ValidationUtils.normalizeComponentInstanceName(getSubPathByLastDelimiterAppearance(path)))
-                               .collect(Collectors.toList()));
-               return new StringBuilder().append(String.join(PATH_DELIMITER, pathArray)).append(PATH_DELIMITER).append(r.getName()).toString();
+       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){
+                       result = buildSubstitutedName(componentsCache, getOriginRes.left().value(), Lists.newArrayList(path.subList(0, path.size()-1)), 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(r);
+                       name = getRequirementPath(component, r);
                }
-               log.debug("the requirement {} belongs to resource {} ", name, component.getUniqueId());
+               logger.debug("the requirement {} belongs to resource {} ", name, component.getUniqueId());
                ToscaRequirement toscaRequirement = new ToscaRequirement();
 
                List<Object> occurences = new ArrayList<>();
@@ -230,78 +372,101 @@ public class CapabiltyRequirementConvertor {
                        occurences.add(Integer.valueOf(r.getMaxOccurrences()));
                }
                toscaRequirement.setOccurrences(occurences);
-               // toscaRequirement.setOccurrences(createOcurrencesRange(requirementDefinition.getMinOccurrences(),
-               // requirementDefinition.getMaxOccurrences()));
                toscaRequirement.setNode(r.getNode());
                toscaRequirement.setCapability(r.getCapability());
                toscaRequirement.setRelationship(r.getRelationship());
 
-               ImmutablePair<String, ToscaRequirement> pair = new ImmutablePair<String, ToscaRequirement>(name, toscaRequirement);
-               return pair;
+               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 = ToscaUtils.isAtomicType(component);
+                       boolean isNodeType = ModelConverter.isAtomicComponent(component);
                        for (Map.Entry<String, List<CapabilityDefinition>> entry : capabilities.entrySet()) {
-                               entry.getValue().stream().filter(c -> (!isNodeType || (isNodeType && component.getUniqueId().equals(c.getOwnerId())) || (isNodeType && c.getOwnerId() == null) )).forEach(c -> {
-                                       convertCapabilty(component, toscaCapabilities, isNodeType, c, dataTypes);
-
-                               });
+                               entry.getValue().stream().filter(c -> filter(component, c.getOwnerId())).forEach(c -> convertCapabilty(component, toscaCapabilities, isNodeType, c, dataTypes));
                        }
                } else {
-                       log.debug("No Capabilities for node type");
+                       logger.debug(NO_CAPABILITIES);
                }
 
                return toscaCapabilities;
        }
-       
-       //This function calls on Substitution Mapping region - the component is always non-atomic
-       public Map<String, String[]> convertSubstitutionMappingCapabilities(Component component, Map<String, DataTypeDefinition> dataTypes) {
-               Map<String, List<CapabilityDefinition>> capabilities = component.getCapabilities();
-               Map<String, String[]> toscaCapabilities = new HashMap<>();
+
+       /**
+        * 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 -> {
-                                       String fullCapName;
-                                       String sourceReqName;
-                                       if(ToscaUtils.isComplexVfc(component)){
-                                               fullCapName = c.getName();
-                                               sourceReqName = c.getParentName();
-                                       } else {
-                                               fullCapName = getCapabilityPath(c);
-                                               sourceReqName = getSubPathByFirstDelimiterAppearance(fullCapName);
-                                       }
-                                       log.debug("the capabilty {} belongs to resource {} ", fullCapName, component.getUniqueId());
-                                       if(sourceReqName!= null){
-                                               toscaCapabilities.put(fullCapName, new String[]{c.getOwnerName(), sourceReqName});
-                                       }
-                               });
+                               entry.getValue().stream().forEach(c -> convertCapabilty(proxyComponent, toscaCapabilities, isNodeType, c, dataTypes));
                        }
                } else {
-                       log.debug("No Capabilities for node type");
+                       logger.debug(NO_CAPABILITIES);
                }
 
                return toscaCapabilities;
        }
-       
-       private String getCapabilityPath(CapabilityDefinition c)  {
-               List<String> pathArray = Lists.reverse(c.getPath().stream()
-                               .map(path -> ValidationUtils.normalizeComponentInstanceName(getSubPathByLastDelimiterAppearance(path)))
-                               .collect(Collectors.toList()));
-               return new StringBuilder().append(String.join(PATH_DELIMITER, pathArray)).append(PATH_DELIMITER).append(c.getName()).toString();
+
+       /**
+        * 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  = null;
+               if (capabilities != null) {
+                       res = buildAddSubstitutionMappingsCapabilities(componentsCache, component, capabilities);
+               } else {
+                       logger.debug(NO_CAPABILITIES);
+                       res = Either.left(new HashMap<>());
+               }
+               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);
+                       name = getCapabilityPath(c, component);
                }
-               log.debug("the capabilty {} belongs to resource {} ", name, component.getUniqueId());
+               logger.debug("the capabilty {} belongs to resource {} ", name, component.getUniqueId());
                ToscaCapability toscaCapability = new ToscaCapability();
                toscaCapability.setDescription(c.getDescription());
                toscaCapability.setType(c.getType());
@@ -327,5 +492,61 @@ public class CapabiltyRequirementConvertor {
                }
                toscaCapabilities.put(name, toscaCapability);
        }
+       
+       Either<String, Boolean> buildSubstitutedName(Map<String, Component> originComponents, 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)){
+                       Collections.reverse(path);
+                       Iterator<String> instanceIdIter = path.iterator();
+                       nameBuiltSuccessfully = appendNameRecursively(originComponents, originComponent, instanceIdIter, substitutedName);
+               }
+               if(nameBuiltSuccessfully){
+                       result = Either.left(substitutedName.append(name).toString());
+               } else {
+                       result = Either.right(nameBuiltSuccessfully);
+               }
+               return result;
+       }
+
+       private boolean appendNameRecursively(Map<String, Component> originComponents, Component originComponent, Iterator<String> instanceIdIter, StringBuilder substitutedName) {
+               if(CollectionUtils.isNotEmpty(originComponent.getComponentInstances()) && instanceIdIter.hasNext()){
+                       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;
+                       }
+                       Either<Component, Boolean> getOriginRes = getOriginComponent(originComponents, instanceOpt.get());
+                       if(getOriginRes.isRight()){
+                               return false;
+                       }
+                       appendNameRecursively(originComponents, getOriginRes.left().value(), instanceIdIter, substitutedName);
+                       substitutedName.append(instanceOpt.get().getNormalizedName()).append('.');
+                       return true;
+               }
+               return true;
+       }
+
+       private Either<Component, Boolean> getOriginComponent(Map<String, Component> originComponents, ComponentInstance instance) {
+               Either<Component, Boolean> result;
+               Either<Component, StorageOperationStatus> getOriginRes;
+               if(originComponents.containsKey(instance.getComponentUid())){
+                       result = Either.left(originComponents.get(instance.getComponentUid()));
+               } else {
+                       ComponentParametersView filter = new ComponentParametersView(true);
+                       filter.setIgnoreComponentInstances(false);
+                       getOriginRes = toscaOperationFacade.getToscaElement(instance.getComponentUid(), filter);
+                       if(getOriginRes.isRight()){
+                               logger.debug("Failed to get an origin component with uniqueId {}", instance.getComponentUid());
+                               result = Either.right(false);
+                       } else {
+                               result = Either.left(getOriginRes.left().value());
+                               originComponents.put(getOriginRes.left().value().getUniqueId(), getOriginRes.left().value());
+                       }
+               }
+               return result;
+       }
 
 }