Sync Integ to Master
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / tosca / CapabiltyRequirementConvertor.java
index 886b654..4dbbf92 100644 (file)
 
 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