[SDC-29] Amdocs OnBoard 1707 initial commit.
[sdc.git] / openecomp-be / lib / openecomp-tosca-lib / src / main / java / org / openecomp / sdc / tosca / services / impl / ToscaAnalyzerServiceImpl.java
index a11bff4..e7aacb9 100644 (file)
@@ -24,25 +24,37 @@ import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.MapUtils;
 import org.openecomp.core.utilities.CommonMethods;
 import org.openecomp.sdc.common.errors.CoreException;
-import org.openecomp.sdc.tosca.datatypes.ToscaCapabilityType;
+import org.openecomp.sdc.datatypes.error.ErrorLevel;
+import org.openecomp.sdc.logging.context.impl.MdcDataErrorMessage;
+import org.openecomp.sdc.logging.types.LoggerConstants;
+import org.openecomp.sdc.logging.types.LoggerErrorCode;
+import org.openecomp.sdc.logging.types.LoggerErrorDescription;
+import org.openecomp.sdc.logging.types.LoggerTragetServiceName;
 import org.openecomp.sdc.tosca.datatypes.ToscaElementTypes;
 import org.openecomp.sdc.tosca.datatypes.ToscaNodeType;
 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
+import org.openecomp.sdc.tosca.datatypes.model.AttributeDefinition;
 import org.openecomp.sdc.tosca.datatypes.model.CapabilityType;
 import org.openecomp.sdc.tosca.datatypes.model.Import;
 import org.openecomp.sdc.tosca.datatypes.model.NodeTemplate;
 import org.openecomp.sdc.tosca.datatypes.model.NodeType;
+import org.openecomp.sdc.tosca.datatypes.model.ParameterDefinition;
+import org.openecomp.sdc.tosca.datatypes.model.PropertyDefinition;
+import org.openecomp.sdc.tosca.datatypes.model.PropertyType;
 import org.openecomp.sdc.tosca.datatypes.model.RequirementAssignment;
 import org.openecomp.sdc.tosca.datatypes.model.ServiceTemplate;
 import org.openecomp.sdc.tosca.errors.ToscaInvalidEntryNotFoundErrorBuilder;
 import org.openecomp.sdc.tosca.errors.ToscaInvalidSubstituteNodeTemplatePropertiesErrorBuilder;
 import org.openecomp.sdc.tosca.errors.ToscaInvalidSubstitutionServiceTemplateErrorBuilder;
 import org.openecomp.sdc.tosca.errors.ToscaNodeTypeNotFoundErrorBuilder;
+import org.openecomp.sdc.tosca.services.DataModelUtil;
 import org.openecomp.sdc.tosca.services.ToscaAnalyzerService;
 import org.openecomp.sdc.tosca.services.ToscaConstants;
+import org.openecomp.sdc.tosca.services.ToscaUtil;
 import org.openecomp.sdc.tosca.services.yamlutil.ToscaExtensionYamlUtil;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -53,7 +65,7 @@ import java.util.Set;
 
 public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
   /*
-  node template with type equal to node type or derived from node type.
+  node template with type equal to node type or derived from node type
    */
   @Override
   public Map<String, NodeTemplate> getNodeTemplatesByType(ServiceTemplate serviceTemplate,
@@ -74,6 +86,19 @@ public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
     return nodeTemplates;
   }
 
+  @Override
+  public Optional<NodeType> fetchNodeType(String nodeTypeKey, Collection<ServiceTemplate>
+      serviceTemplates) {
+    Optional<Map<String, NodeType>> nodeTypeMap = serviceTemplates.stream()
+        .map(st -> st.getNode_types())
+        .filter(nodeTypes -> Objects.nonNull(nodeTypes) && nodeTypes.containsKey(nodeTypeKey))
+        .findFirst();
+    if (nodeTypeMap.isPresent()) {
+      return Optional.ofNullable(nodeTypeMap.get().values().iterator().next());
+    }
+    return Optional.empty();
+  }
+
   @Override
   public boolean isTypeOf(NodeTemplate nodeTemplate, String nodeType,
                           ServiceTemplate serviceTemplate, ToscaServiceModel toscaServiceModel) {
@@ -92,88 +117,6 @@ public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
         new ToscaNodeTypeNotFoundErrorBuilder(nodeTemplate.getType()).build()));
   }
 
-
-  private Optional<Boolean> isNodeTypeExistInServiceTemplateHierarchy(String nodeTypeToMatch,
-                                                               String nodeTypeToSearch,
-                                                               ServiceTemplate serviceTemplate,
-                                                               ToscaServiceModel toscaServiceModel,
-                                                               Set<String> analyzedImportFiles) {
-    Map<String, NodeType> searchableNodeTypes = serviceTemplate.getNode_types();
-    if (!MapUtils.isEmpty(searchableNodeTypes)) {
-      NodeType nodeType = searchableNodeTypes.get(nodeTypeToSearch);
-      if (Objects.nonNull(nodeType)) {
-        if (Objects.equals(nodeType.getDerived_from(), nodeTypeToMatch)) {
-          return Optional.of(true);
-        } else if (isNodeTypeIsToscaRoot(nodeType)) {
-          return Optional.of(false);
-        } else {
-          return isNodeTypeExistInServiceTemplateHierarchy(nodeTypeToMatch,
-              nodeType.getDerived_from(), serviceTemplate, toscaServiceModel, null);
-        }
-      } else {
-        return isNodeTypeExistInImports(nodeTypeToMatch, nodeTypeToSearch, serviceTemplate,
-            toscaServiceModel, analyzedImportFiles);
-      }
-    }
-    return isNodeTypeExistInImports(nodeTypeToMatch, nodeTypeToSearch, serviceTemplate,
-        toscaServiceModel, analyzedImportFiles);
-
-  }
-
-  private Optional<Boolean> isNodeTypeExistInImports(String nodeTypeToMatch,
-                                                     String nodeTypeToSearch,
-                                                     ServiceTemplate serviceTemplate,
-                                                     ToscaServiceModel toscaServiceModel,
-                                                     Set<String> analyzedImportFiles) {
-    Map<String, Import> imports = serviceTemplate.getImports();
-    if (imports == null) {
-      return Optional.empty();
-    }
-
-    analyzedImportFiles = createAnalyzedImportFilesSet(analyzedImportFiles);
-    for (Import anImport : imports.values()) {
-      if (Objects.isNull(anImport) || Objects.isNull(anImport.getFile())) {
-        throw new RuntimeException("import without file entry");
-      }
-      String importFile = anImport.getFile();
-      if (analyzedImportFiles.contains(importFile)) {
-        continue;
-      }
-      addImportFileToAnalyzedImportFilesSet(analyzedImportFiles, importFile);
-      ServiceTemplate template = toscaServiceModel.getServiceTemplates().get(importFile);
-      Optional<Boolean> nodeTypeExistInServiceTemplateHierarchy =
-          isNodeTypeExistInServiceTemplateHierarchy(nodeTypeToMatch, nodeTypeToSearch, template,
-              toscaServiceModel, analyzedImportFiles);
-      if (nodeTypeExistInServiceTemplateHierarchy.isPresent()) {
-        if (nodeTypeExistInServiceTemplateHierarchy.get()) {
-          return Optional.of(true);
-        }
-      }
-    }
-    return Optional.of(false);
-  }
-
-  private Set<String> addImportFileToAnalyzedImportFilesSet(Set<String> analyzedImportFiles,
-                                                            String importFile) {
-    analyzedImportFiles.add(importFile);
-    return analyzedImportFiles;
-  }
-
-  private Set<String> createAnalyzedImportFilesSet(Set<String> analyzedImportFiles) {
-    if (Objects.isNull(analyzedImportFiles)) {
-      analyzedImportFiles = new HashSet<>();
-    }
-    return analyzedImportFiles;
-  }
-
-  private boolean isNodeTypeIsToscaRoot(NodeType stNodeType) {
-    return Objects.equals(stNodeType.getDerived_from(), ToscaNodeType.ROOT.getDisplayName());
-  }
-
-  private boolean isNodeTemplateOfTypeNodeType(NodeTemplate nodeTemplate, String nodeType) {
-    return Objects.equals(nodeTemplate.getType(), nodeType);
-  }
-
   @Override
   public List<RequirementAssignment> getRequirements(NodeTemplate nodeTemplate,
                                                      String requirementId) {
@@ -197,8 +140,8 @@ public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
                                                     String nodeTemplateId) {
     if ((serviceTemplate.getTopology_template() != null)
         && (serviceTemplate.getTopology_template().getNode_templates() != null)
-        && (serviceTemplate.getTopology_template().getNode_templates()
-        .get(nodeTemplateId) != null)) {
+        && (serviceTemplate.getTopology_template().getNode_templates().get(nodeTemplateId)
+        != null)) {
       return Optional
           .of(serviceTemplate.getTopology_template().getNode_templates().get(nodeTemplateId));
     }
@@ -214,13 +157,16 @@ public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
 
     if (substitutableNodeTemplate.getProperties() != null
         && substitutableNodeTemplate.getProperties()
-            .get(ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME) != null) {
+        .get(ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME) != null) {
       Object serviceTemplateFilter = substitutableNodeTemplate.getProperties()
           .get(ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME);
       if (serviceTemplateFilter != null && serviceTemplateFilter instanceof Map) {
         Object substituteServiceTemplate = ((Map) serviceTemplateFilter)
             .get(ToscaConstants.SUBSTITUTE_SERVICE_TEMPLATE_PROPERTY_NAME);
         if (substituteServiceTemplate == null) {
+          MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
+              LoggerTragetServiceName.ADD_ENTITIES_TO_TOSCA, ErrorLevel.ERROR.name(),
+              LoggerErrorCode.DATA_ERROR.getErrorCode(), LoggerErrorDescription.INVALID_PROPERTY);
           throw new CoreException(
               new ToscaInvalidSubstituteNodeTemplatePropertiesErrorBuilder(substituteNodeTemplateId)
                   .build());
@@ -228,6 +174,9 @@ public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
         return Optional.of(substituteServiceTemplate.toString());
       }
     }
+    MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
+        LoggerTragetServiceName.ADD_ENTITIES_TO_TOSCA, ErrorLevel.ERROR.name(),
+        LoggerErrorCode.DATA_ERROR.getErrorCode(), LoggerErrorDescription.INVALID_PROPERTY);
     throw new CoreException(
         new ToscaInvalidSubstituteNodeTemplatePropertiesErrorBuilder(substituteNodeTemplateId)
             .build());
@@ -255,28 +204,6 @@ public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
     return substitutableNodeTemplates;
   }
 
-  private boolean isSubstitutableNodeTemplate(NodeTemplate nodeTemplate) {
-    return nodeTemplate.getDirectives() != null
-        && nodeTemplate.getDirectives().contains(ToscaConstants
-        .NODE_TEMPLATE_DIRECTIVE_SUBSTITUTABLE);
-  }
-
-  private boolean isSubstitutionServiceTemplate(String substituteServiceTemplateFileName,
-                                                ServiceTemplate substituteServiceTemplate) {
-    if (substituteServiceTemplate != null
-        && substituteServiceTemplate.getTopology_template() != null
-        && substituteServiceTemplate.getTopology_template().getSubstitution_mappings() != null) {
-      if (substituteServiceTemplate.getTopology_template().getSubstitution_mappings()
-          .getNode_type() == null) {
-        throw new CoreException(new ToscaInvalidSubstitutionServiceTemplateErrorBuilder(
-            substituteServiceTemplateFileName).build());
-      }
-      return true;
-    }
-    return false;
-
-  }
-
   @Override
   public Optional<Map.Entry<String, NodeTemplate>> getSubstitutionMappedNodeTemplateByExposedReq(
       String substituteServiceTemplateFileName, ServiceTemplate substituteServiceTemplate,
@@ -319,7 +246,6 @@ public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
     return Optional.empty();
   }
 
-
   /*
   match only for the input which is not null
    */
@@ -361,62 +287,245 @@ public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
       case CAPABILITY_TYPE:
         returnEntity = new CapabilityType();
         break;
+      case NODE_TYPE:
+        returnEntity = new NodeType();
+        break;
       default:
+        MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
+            LoggerTragetServiceName.ADD_ENTITIES_TO_TOSCA, ErrorLevel.ERROR.name(),
+            LoggerErrorCode.DATA_ERROR.getErrorCode(), LoggerErrorDescription.UNSUPPORTED_ENTITY);
         throw new RuntimeException(
             "Entity[" + elementType + "] id[" + typeId + "] flat not supported");
     }
 
-    scanAnFlatEntity(elementType, typeId, returnEntity, serviceTemplate, toscaModel);
+    scanAnFlatEntity(elementType, typeId, returnEntity, serviceTemplate, toscaModel,
+        new ArrayList<String>(), 0);
 
 
     return returnEntity;
   }
 
-  private void scanAnFlatEntity(ToscaElementTypes elementType, String typeId, Object entity,
-                                ServiceTemplate serviceTemplate, ToscaServiceModel toscaModel) {
+  @Override
+  public boolean isSubstitutableNodeTemplate(NodeTemplate nodeTemplate) {
+    return nodeTemplate.getDirectives() != null
+        && nodeTemplate.getDirectives().contains(ToscaConstants
+        .NODE_TEMPLATE_DIRECTIVE_SUBSTITUTABLE);
+  }
+
+  private Optional<Boolean> isNodeTypeExistInServiceTemplateHierarchy(
+      String nodeTypeToMatch,
+      String nodeTypeToSearch,
+      ServiceTemplate serviceTemplate,
+      ToscaServiceModel toscaServiceModel,
+      Set<String> analyzedImportFiles) {
+    Map<String, NodeType> searchableNodeTypes = serviceTemplate.getNode_types();
+    if (!MapUtils.isEmpty(searchableNodeTypes)) {
+      NodeType nodeType = searchableNodeTypes.get(nodeTypeToSearch);
+      if (Objects.nonNull(nodeType)) {
+        if (Objects.equals(nodeType.getDerived_from(), nodeTypeToMatch)) {
+          return Optional.of(true);
+        } else if (isNodeTypeIsToscaRoot(nodeType)) {
+          return Optional.of(false);
+        } else {
+          return isNodeTypeExistInServiceTemplateHierarchy(nodeTypeToMatch,
+              nodeType.getDerived_from(), serviceTemplate, toscaServiceModel, null);
+        }
+      } else {
+        return isNodeTypeExistInImports(nodeTypeToMatch, nodeTypeToSearch, serviceTemplate,
+            toscaServiceModel, analyzedImportFiles);
+      }
+    }
+    return isNodeTypeExistInImports(nodeTypeToMatch, nodeTypeToSearch, serviceTemplate,
+        toscaServiceModel, analyzedImportFiles);
+
+  }
+
+  private Optional<Boolean> isNodeTypeExistInImports(String nodeTypeToMatch,
+                                                     String nodeTypeToSearch,
+                                                     ServiceTemplate serviceTemplate,
+                                                     ToscaServiceModel toscaServiceModel,
+                                                     Set<String> filesScanned) {
+    List<Map<String, Import>> imports = serviceTemplate.getImports();
+    if (CollectionUtils.isEmpty(imports)) {
+      return Optional.empty();
+    }
+
+    filesScanned = createFilesScannedSet(filesScanned);
+
+    for (Map<String, Import> map : imports) {
+      ToscaExtensionYamlUtil toscaExtensionYamlUtil = new ToscaExtensionYamlUtil();
+      Import anImport = toscaExtensionYamlUtil
+          .yamlToObject(toscaExtensionYamlUtil.objectToYaml(map.values().iterator().next()),
+              Import.class);
+      if (Objects.isNull(anImport) || Objects.isNull(anImport.getFile())) {
+        throw new RuntimeException("import without file entry");
+      }
+      String importFile = anImport.getFile();
+      ServiceTemplate template =
+          toscaServiceModel.getServiceTemplates().get(fetchFileNameForImport(importFile,
+              serviceTemplate.getMetadata() == null ? null
+                  : serviceTemplate.getMetadata().get("filename")));
+      if (filesScanned.contains(ToscaUtil.getServiceTemplateFileName(template))) {
+        continue;
+      } else {
+        filesScanned.add(ToscaUtil.getServiceTemplateFileName(template));
+      }
+      Optional<Boolean> nodeTypeExistInServiceTemplateHierarchy =
+          isNodeTypeExistInServiceTemplateHierarchy(nodeTypeToMatch, nodeTypeToSearch, template,
+              toscaServiceModel, filesScanned);
+      if (nodeTypeExistInServiceTemplateHierarchy.isPresent()) {
+        if (nodeTypeExistInServiceTemplateHierarchy.get()) {
+          filesScanned.clear();
+          return Optional.of(true);
+        }
+      }
+
+    }
+    return Optional.of(false);
+  }
+
+  private Set<String> addImportFileToAnalyzedImportFilesSet(Set<String> analyzedImportFiles,
+                                                            String importFile) {
+    analyzedImportFiles.add(importFile);
+    return analyzedImportFiles;
+  }
+
+  private Set<String> createFilesScannedSet(Set<String> filesScanned) {
+    if (Objects.isNull(filesScanned)) {
+      filesScanned = new HashSet<>();
+    }
+    return filesScanned;
+  }
+
+  private boolean isNodeTypeIsToscaRoot(NodeType stNodeType) {
+    return Objects.equals(stNodeType.getDerived_from(), ToscaNodeType.NATIVE_ROOT);
+  }
+
+  private boolean isNodeTemplateOfTypeNodeType(NodeTemplate nodeTemplate, String nodeType) {
+    return Objects.equals(nodeTemplate.getType(), nodeType);
+  }
+
+  private boolean isSubstitutionServiceTemplate(String substituteServiceTemplateFileName,
+                                                ServiceTemplate substituteServiceTemplate) {
+    if (substituteServiceTemplate != null
+        && substituteServiceTemplate.getTopology_template() != null
+        && substituteServiceTemplate.getTopology_template().getSubstitution_mappings() != null) {
+      if (substituteServiceTemplate.getTopology_template().getSubstitution_mappings()
+          .getNode_type() == null) {
+        throw new CoreException(new ToscaInvalidSubstitutionServiceTemplateErrorBuilder(
+            substituteServiceTemplateFileName).build());
+      }
+      return true;
+    }
+    return false;
+
+  }
+
+  private boolean scanAnFlatEntity(ToscaElementTypes elementType, String typeId, Object entity,
+                                   ServiceTemplate serviceTemplate, ToscaServiceModel toscaModel,
+                                   List<String> filesScanned, int rootScanStartInx) {
 
 
     boolean entityFound =
         enrichEntityFromCurrentServiceTemplate(elementType, typeId, entity, serviceTemplate,
-            toscaModel);
+            toscaModel, filesScanned, rootScanStartInx);
     if (!entityFound) {
-      Map<String, Import> imports = serviceTemplate.getImports();
-      if (MapUtils.isEmpty(imports)) {
-        return;
+      List<Map<String, Import>> imports = serviceTemplate.getImports();
+      if (CollectionUtils.isEmpty(imports)) {
+        return false;
       }
-      for (Import importServiceTemplate : imports.values()) {
-        ServiceTemplate template =
-            toscaModel.getServiceTemplates().get(importServiceTemplate.getFile());
-        scanAnFlatEntity(elementType, typeId, entity, template, toscaModel);
+      ToscaExtensionYamlUtil toscaExtensionYamlUtil = new ToscaExtensionYamlUtil();
+      boolean found = false;
+      for (Map<String, Import> importMap : imports) {
+        if (found) {
+          return true;
+        }
+        String filename = "";
+        for (Object importObject : importMap.values()) {
+          Import importServiceTemplate = toscaExtensionYamlUtil
+              .yamlToObject(toscaExtensionYamlUtil.objectToYaml(importObject), Import.class);
+          filename = fetchFileNameForImport(importServiceTemplate.getFile(),
+              serviceTemplate.getMetadata() == null ? null : serviceTemplate.getMetadata().get
+                  ("filename"));
+          if (filesScanned.contains(filename)) {
+            return false;
+          } else {
+            filesScanned.add(filename);
+          }
+          ServiceTemplate template =
+              toscaModel.getServiceTemplates()
+                  .get(filename);
+          found =
+              scanAnFlatEntity(elementType, typeId, entity, template, toscaModel, filesScanned,
+                  filesScanned.size());
+        }
       }
+      return found;
     }
+    return true;
+  }
 
+  private String fetchFileNameForImport(String importServiceTemplateFile,
+                                        String currentMetadatafileName) {
+    if (importServiceTemplateFile.contains("../")) {
+      return importServiceTemplateFile.replace("../", "");
+    } else if (importServiceTemplateFile.contains("/")) {
+      return importServiceTemplateFile;
+    } else if (currentMetadatafileName != null) {
+      return currentMetadatafileName.substring(0, currentMetadatafileName.indexOf("/")) + "/" +
+          importServiceTemplateFile;
+    } else {
+      return importServiceTemplateFile;
+    }
 
   }
 
   private boolean enrichEntityFromCurrentServiceTemplate(ToscaElementTypes elementType,
                                                          String typeId, Object entity,
                                                          ServiceTemplate serviceTemplate,
-                                                         ToscaServiceModel toscaModel) {
+                                                         ToscaServiceModel toscaModel,
+                                                         List<String> filesScanned,
+                                                         int rootScanStartInx) {
     String derivedFrom;
     switch (elementType) {
       case CAPABILITY_TYPE:
         if (serviceTemplate.getCapability_types() != null
             && serviceTemplate.getCapability_types().containsKey(typeId)) {
 
+          filesScanned.clear();
           CapabilityType targetCapabilityType = ((CapabilityType) entity);
           CapabilityType sourceCapabilityType = serviceTemplate.getCapability_types().get(typeId);
           derivedFrom = sourceCapabilityType.getDerived_from();
-          if (derivedFrom != null
-              && !ToscaCapabilityType.NFV_METRIC.getDisplayName().equals(derivedFrom)) {
-            scanAnFlatEntity(elementType, derivedFrom, entity, serviceTemplate, toscaModel);
+          if (derivedFrom != null) {
+            scanAnFlatEntity(elementType, derivedFrom, entity, serviceTemplate, toscaModel,
+                filesScanned, rootScanStartInx);
           }
           combineCapabilityTypeInfo(sourceCapabilityType, targetCapabilityType);
         } else {
           return false;
         }
         break;
+      case NODE_TYPE:
+        if (serviceTemplate.getNode_types() != null
+            && serviceTemplate.getNode_types().containsKey(typeId)) {
+
+          filesScanned.clear();
+          NodeType targetNodeType = ((NodeType) entity);
+          NodeType sourceNodeType = serviceTemplate.getNode_types().get(typeId);
+          derivedFrom = sourceNodeType.getDerived_from();
+          if (derivedFrom != null) {
+            scanAnFlatEntity(elementType, derivedFrom, entity, serviceTemplate, toscaModel,
+                filesScanned, rootScanStartInx);
+          }
+          combineNodeTypeInfo(sourceNodeType, targetNodeType);
+        } else {
+          return false;
+        }
+        break;
       default:
+        MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
+            LoggerTragetServiceName.ADD_ENTITIES_TO_TOSCA, ErrorLevel.ERROR.name(),
+            LoggerErrorCode.DATA_ERROR.getErrorCode(), LoggerErrorDescription.UNSUPPORTED_ENTITY);
         throw new RuntimeException(
             "Entity[" + elementType + "] id[" + typeId + "] flat not supported");
     }
@@ -426,37 +535,44 @@ public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
 
   }
 
+  private void combineNodeTypeInfo(NodeType sourceNodeType, NodeType targetNodeType) {
+    targetNodeType.setDerived_from(sourceNodeType.getDerived_from());
+    targetNodeType.setDescription(sourceNodeType.getDescription());
+    targetNodeType.setVersion(sourceNodeType.getVersion());
+    targetNodeType.setProperties(
+        CommonMethods.mergeMaps(targetNodeType.getProperties(), sourceNodeType.getProperties()));
+    targetNodeType.setInterfaces(
+        CommonMethods.mergeMaps(targetNodeType.getInterfaces(), sourceNodeType.getInterfaces()));
+    targetNodeType.setArtifacts(
+        CommonMethods.mergeMaps(targetNodeType.getArtifacts(), sourceNodeType.getArtifacts()));
+    targetNodeType.setAttributes(
+        CommonMethods.mergeMaps(targetNodeType.getAttributes(), sourceNodeType.getAttributes()));
+    targetNodeType.setCapabilities(CommonMethods
+        .mergeMaps(targetNodeType.getCapabilities(), sourceNodeType.getCapabilities()));
+    targetNodeType.setRequirements(CommonMethods
+        .mergeListsOfMap(targetNodeType.getRequirements(), sourceNodeType.getRequirements()));
+
+  }
+
+
   private void combineCapabilityTypeInfo(CapabilityType sourceCapabilityType,
                                          CapabilityType targetCapabilityType) {
-    if (MapUtils.isNotEmpty(sourceCapabilityType.getAttributes())) {
-      if (targetCapabilityType.getAttributes() == null) {
-        targetCapabilityType.setAttributes(new HashMap<>());
-      }
-      targetCapabilityType.getAttributes().putAll(sourceCapabilityType.getAttributes());
-    }
 
-    if (MapUtils.isNotEmpty(sourceCapabilityType.getProperties())) {
-      if (targetCapabilityType.getProperties() == null) {
-        targetCapabilityType.setProperties(new HashMap<>());
-      }
-      targetCapabilityType.getProperties().putAll(sourceCapabilityType.getProperties());
-    }
+    targetCapabilityType.setAttributes(CommonMethods
+        .mergeMaps(targetCapabilityType.getAttributes(), sourceCapabilityType.getAttributes()));
+    targetCapabilityType.setProperties(CommonMethods
+        .mergeMaps(targetCapabilityType.getProperties(), sourceCapabilityType.getProperties()));
+    targetCapabilityType.setValid_source_types(CommonMethods
+        .mergeLists(targetCapabilityType.getValid_source_types(),
+            sourceCapabilityType.getValid_source_types()));
 
-    if (CollectionUtils.isNotEmpty(sourceCapabilityType.getValid_source_types())) {
-      if (targetCapabilityType.getValid_source_types() == null) {
-        targetCapabilityType.setValid_source_types(new ArrayList<>());
-      }
-      targetCapabilityType.getValid_source_types()
-          .addAll(sourceCapabilityType.getValid_source_types());
-    }
-
-    if (CommonMethods.isEmpty(sourceCapabilityType.getDerived_from())) {
+    if (!CommonMethods.isEmpty(sourceCapabilityType.getDerived_from())) {
       targetCapabilityType.setDerived_from(sourceCapabilityType.getDerived_from());
     }
-    if (CommonMethods.isEmpty(sourceCapabilityType.getDescription())) {
+    if (!CommonMethods.isEmpty(sourceCapabilityType.getDescription())) {
       targetCapabilityType.setDescription(sourceCapabilityType.getDescription());
     }
-    if (CommonMethods.isEmpty(sourceCapabilityType.getVersion())) {
+    if (!CommonMethods.isEmpty(sourceCapabilityType.getVersion())) {
       targetCapabilityType.setVersion(sourceCapabilityType.getVersion());
     }
 
@@ -464,4 +580,121 @@ public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
   }
 
 
+  /*
+ * Create node type according to the input substitution service template, while the substitution
+ * service template can be mappted to this node type, for substitution mapping.
+ *
+ * @param substitutionServiceTemplate  substitution serivce template
+ * @param nodeTypeDerivedFromValue derived from value for the created node type
+ * @return the node type
+ */
+  @Override
+  public NodeType createInitSubstitutionNodeType(ServiceTemplate substitutionServiceTemplate,
+                                                 String nodeTypeDerivedFromValue) {
+    NodeType substitutionNodeType = new NodeType();
+    substitutionNodeType.setDerived_from(nodeTypeDerivedFromValue);
+    substitutionNodeType.setDescription(substitutionServiceTemplate.getDescription());
+    substitutionNodeType
+        .setProperties(manageSubstitutionNodeTypeProperties(substitutionServiceTemplate));
+    substitutionNodeType
+        .setAttributes(manageSubstitutionNodeTypeAttributes(substitutionServiceTemplate));
+    return substitutionNodeType;
+  }
+
+  private Map<String, PropertyDefinition> manageSubstitutionNodeTypeProperties(
+      ServiceTemplate substitutionServiceTemplate) {
+    Map<String, PropertyDefinition> substitutionNodeTypeProperties = new HashMap<>();
+    Map<String, ParameterDefinition> properties =
+        substitutionServiceTemplate.getTopology_template().getInputs();
+    if (properties == null) {
+      return null;
+    }
+
+    PropertyDefinition propertyDefinition;
+    String toscaPropertyName;
+    for (Map.Entry<String, ParameterDefinition> entry : properties.entrySet()) {
+      toscaPropertyName = entry.getKey();
+      propertyDefinition = new PropertyDefinition();
+      ParameterDefinition parameterDefinition =
+          substitutionServiceTemplate.getTopology_template().getInputs().get(toscaPropertyName);
+      propertyDefinition.setType(parameterDefinition.getType());
+      propertyDefinition.setDescription(parameterDefinition.getDescription());
+      propertyDefinition.set_default(parameterDefinition.get_default());
+      if (parameterDefinition.getRequired() != null) {
+        propertyDefinition.setRequired(parameterDefinition.getRequired());
+      }
+      if (propertyDefinition.get_default() != null) {
+        propertyDefinition.setRequired(false);
+      }
+      if (!CollectionUtils.isEmpty(parameterDefinition.getConstraints())) {
+        propertyDefinition.setConstraints(parameterDefinition.getConstraints());
+      }
+      propertyDefinition.setEntry_schema(parameterDefinition.getEntry_schema());
+      if (parameterDefinition.getStatus() != null) {
+        propertyDefinition.setStatus(parameterDefinition.getStatus());
+      }
+      substitutionNodeTypeProperties.put(toscaPropertyName, propertyDefinition);
+    }
+    return substitutionNodeTypeProperties;
+  }
+
+  private Map<String, AttributeDefinition> manageSubstitutionNodeTypeAttributes(
+      ServiceTemplate substitutionServiceTemplate) {
+    Map<String, AttributeDefinition> substitutionNodeTypeAttributes = new HashMap<>();
+    Map<String, ParameterDefinition> attributes =
+        substitutionServiceTemplate.getTopology_template().getOutputs();
+    if (attributes == null) {
+      return null;
+    }
+    AttributeDefinition attributeDefinition;
+    String toscaAttributeName;
+
+    for (Map.Entry<String, ParameterDefinition> entry : attributes.entrySet()) {
+      attributeDefinition = new AttributeDefinition();
+      toscaAttributeName = entry.getKey();
+      ParameterDefinition parameterDefinition =
+          substitutionServiceTemplate.getTopology_template().getOutputs().get(toscaAttributeName);
+      if (parameterDefinition.getType() != null && !parameterDefinition.getType().isEmpty()) {
+        attributeDefinition.setType(parameterDefinition.getType());
+      } else {
+        attributeDefinition.setType(PropertyType.STRING.getDisplayName());
+      }
+      attributeDefinition.setDescription(parameterDefinition.getDescription());
+      attributeDefinition.set_default(parameterDefinition.get_default());
+      attributeDefinition.setEntry_schema(parameterDefinition.getEntry_schema());
+      if (Objects.nonNull(parameterDefinition.getStatus())) {
+        attributeDefinition.setStatus(parameterDefinition.getStatus());
+      }
+      substitutionNodeTypeAttributes.put(toscaAttributeName, attributeDefinition);
+    }
+    return substitutionNodeTypeAttributes;
+  }
+
+  /**
+   * Checks if the requirement exists in the node template.
+   *
+   * @param nodeTemplate          the node template
+   * @param requirementId         the requirement id
+   * @param requirementAssignment the requirement assignment
+   * @return true if the requirement already exists and false otherwise
+   */
+  public boolean isRequirementExistInNodeTemplate(NodeTemplate nodeTemplate,
+                                                  String requirementId,
+                                                  RequirementAssignment requirementAssignment) {
+    boolean result = false;
+    List<Map<String, RequirementAssignment>> nodeTemplateRequirements = nodeTemplate
+        .getRequirements();
+    if (nodeTemplateRequirements != null) {
+      for (Map<String, RequirementAssignment> requirement : nodeTemplateRequirements) {
+        if (requirement.containsKey(requirementId)) {
+          result = DataModelUtil.compareRequirementAssignment(requirementAssignment,
+              requirement.get(requirementId));
+          if (result) {
+            break;
+          }
+        }
+      }
+    }
+    return result;
+  }
 }