[SDC] Onboarding 1710 rebase.
[sdc.git] / openecomp-be / lib / openecomp-tosca-lib / src / main / java / org / openecomp / sdc / tosca / services / impl / ToscaAnalyzerServiceImpl.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.openecomp.sdc.tosca.services.impl;
22
23 import org.apache.commons.collections4.CollectionUtils;
24 import org.apache.commons.collections4.MapUtils;
25 import org.openecomp.core.utilities.CommonMethods;
26 import org.openecomp.sdc.common.errors.CoreException;
27 import org.openecomp.sdc.datatypes.error.ErrorLevel;
28 import org.openecomp.sdc.logging.context.impl.MdcDataDebugMessage;
29 import org.openecomp.sdc.logging.context.impl.MdcDataErrorMessage;
30 import org.openecomp.sdc.logging.types.LoggerConstants;
31 import org.openecomp.sdc.logging.types.LoggerErrorCode;
32 import org.openecomp.sdc.logging.types.LoggerErrorDescription;
33 import org.openecomp.sdc.logging.types.LoggerTragetServiceName;
34 import org.openecomp.sdc.tosca.datatypes.ToscaElementTypes;
35 import org.openecomp.sdc.tosca.datatypes.ToscaNodeType;
36 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
37 import org.openecomp.sdc.tosca.datatypes.model.AttributeDefinition;
38 import org.openecomp.sdc.tosca.datatypes.model.CapabilityDefinition;
39 import org.openecomp.sdc.tosca.datatypes.model.CapabilityType;
40 import org.openecomp.sdc.tosca.datatypes.model.Import;
41 import org.openecomp.sdc.tosca.datatypes.model.NodeTemplate;
42 import org.openecomp.sdc.tosca.datatypes.model.NodeType;
43 import org.openecomp.sdc.tosca.datatypes.model.ParameterDefinition;
44 import org.openecomp.sdc.tosca.datatypes.model.PropertyDefinition;
45 import org.openecomp.sdc.tosca.datatypes.model.PropertyType;
46 import org.openecomp.sdc.tosca.datatypes.model.RequirementAssignment;
47 import org.openecomp.sdc.tosca.datatypes.model.RequirementDefinition;
48 import org.openecomp.sdc.tosca.datatypes.model.ServiceTemplate;
49 import org.openecomp.sdc.tosca.errors.ToscaInvalidEntryNotFoundErrorBuilder;
50 import org.openecomp.sdc.tosca.errors.ToscaInvalidSubstituteNodeTemplatePropertiesErrorBuilder;
51 import org.openecomp.sdc.tosca.errors.ToscaInvalidSubstitutionServiceTemplateErrorBuilder;
52 import org.openecomp.sdc.tosca.errors.ToscaNodeTypeNotFoundErrorBuilder;
53 import org.openecomp.sdc.tosca.services.DataModelUtil;
54 import org.openecomp.sdc.tosca.services.ToscaAnalyzerService;
55 import org.openecomp.sdc.tosca.services.ToscaConstants;
56 import org.openecomp.sdc.tosca.services.ToscaUtil;
57 import org.openecomp.sdc.tosca.services.ToscaExtensionYamlUtil;
58
59 import java.util.ArrayList;
60 import java.util.Collection;
61 import java.util.HashMap;
62 import java.util.HashSet;
63 import java.util.List;
64 import java.util.Map;
65 import java.util.Objects;
66 import java.util.Optional;
67 import java.util.Set;
68
69 public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
70
71   protected static MdcDataDebugMessage mdcDataDebugMessage = new MdcDataDebugMessage();
72
73   public List<Map<String, RequirementDefinition>> calculateExposedRequirements(
74       List<Map<String, RequirementDefinition>> nodeTypeRequirementsDefinitionList,
75       Map<String, RequirementAssignment> nodeTemplateRequirementsAssignment) {
76     mdcDataDebugMessage.debugEntryMessage(null, null);
77
78     if (nodeTypeRequirementsDefinitionList == null) {
79       return null;
80     }
81     for (Map.Entry<String, RequirementAssignment> entry : nodeTemplateRequirementsAssignment
82         .entrySet()) {
83       if (entry.getValue().getNode() != null) {
84         Optional<RequirementDefinition> requirementDefinition =
85             DataModelUtil.getRequirementDefinition(nodeTypeRequirementsDefinitionList, entry
86                 .getKey());
87         RequirementDefinition cloneRequirementDefinition;
88         if (requirementDefinition.isPresent()) {
89           cloneRequirementDefinition = requirementDefinition.get().clone();
90           if (!evaluateRequirementFulfillment(cloneRequirementDefinition)) {
91             CommonMethods.mergeEntryInList(entry.getKey(), cloneRequirementDefinition,
92                 nodeTypeRequirementsDefinitionList);
93           } else {
94             DataModelUtil.removeRequirementsDefinition(nodeTypeRequirementsDefinitionList, entry
95                 .getKey());
96           }
97         }
98       } else {
99         for (Map<String, RequirementDefinition> nodeTypeRequirementsMap :
100             nodeTypeRequirementsDefinitionList) {
101           Object max = nodeTypeRequirementsMap.get(entry.getKey()).getOccurrences() != null
102               && nodeTypeRequirementsMap.get(entry.getKey()).getOccurrences().length > 0
103               ? nodeTypeRequirementsMap.get(entry.getKey()).getOccurrences()[1] : 1;
104           Object min = nodeTypeRequirementsMap.get(entry.getKey()).getOccurrences() != null
105               && nodeTypeRequirementsMap.get(entry.getKey()).getOccurrences().length > 0
106               ? nodeTypeRequirementsMap.get(entry.getKey()).getOccurrences()[0] : 1;
107           nodeTypeRequirementsMap.get(entry.getKey()).setOccurrences(new Object[]{min, max});
108         }
109       }
110     }
111
112     mdcDataDebugMessage.debugExitMessage(null, null);
113     return nodeTypeRequirementsDefinitionList;
114   }
115
116   private static boolean evaluateRequirementFulfillment(RequirementDefinition
117                                                             requirementDefinition) {
118     Object[] occurrences = requirementDefinition.getOccurrences();
119     if (occurrences == null) {
120       requirementDefinition.setOccurrences(new Object[]{1, 1});
121       return false;
122     }
123     if (occurrences[1].equals(ToscaConstants.UNBOUNDED)) {
124       return false;
125     }
126
127     if (occurrences[1].equals(1)) {
128       return true;
129     }
130     occurrences[1] = (Integer) occurrences[1] - 1;
131     return false;
132   }
133
134   public Map<String, CapabilityDefinition> calculateExposedCapabilities(
135       Map<String, CapabilityDefinition> nodeTypeCapabilitiesDefinition,
136       Map<String, Map<String, RequirementAssignment>> fullFilledRequirementsDefinitionMap) {
137
138
139     mdcDataDebugMessage.debugEntryMessage(null, null);
140
141     String capabilityKey;
142     String capability;
143     String node;
144     for (Map.Entry<String, Map<String, RequirementAssignment>> entry :
145         fullFilledRequirementsDefinitionMap.entrySet()) {
146       for (Map.Entry<String, RequirementAssignment> fullFilledEntry : entry.getValue().entrySet()) {
147
148         capability = fullFilledEntry.getValue().getCapability();
149         fullFilledEntry.getValue().getOccurrences();
150         node = fullFilledEntry.getValue().getNode();
151         capabilityKey = capability + "_" + node;
152         CapabilityDefinition capabilityDefinition = nodeTypeCapabilitiesDefinition.get(
153             capabilityKey);
154         if (capabilityDefinition != null) {
155           CapabilityDefinition clonedCapabilityDefinition = capabilityDefinition.clone();
156           nodeTypeCapabilitiesDefinition.put(capabilityKey, capabilityDefinition.clone());
157           if (evaluateCapabilityFulfillment(clonedCapabilityDefinition)) {
158             nodeTypeCapabilitiesDefinition.remove(capabilityKey);
159           } else {
160             nodeTypeCapabilitiesDefinition.put(capabilityKey, clonedCapabilityDefinition);
161           }
162         }
163       }
164     }
165
166     Map<String, CapabilityDefinition> exposedCapabilitiesDefinition = new HashMap<>();
167     for (Map.Entry<String, CapabilityDefinition> entry : nodeTypeCapabilitiesDefinition
168         .entrySet()) {
169       exposedCapabilitiesDefinition.put(entry.getKey(), entry.getValue());
170     }
171
172     mdcDataDebugMessage.debugExitMessage(null, null);
173     return exposedCapabilitiesDefinition;
174   }
175
176   private static boolean evaluateCapabilityFulfillment(CapabilityDefinition capabilityDefinition) {
177
178     Object[] occurrences = capabilityDefinition.getOccurrences();
179     if (occurrences == null) {
180       capabilityDefinition.setOccurrences(new Object[]{1, ToscaConstants.UNBOUNDED});
181       return false;
182     }
183     if (occurrences[1].equals(ToscaConstants.UNBOUNDED)) {
184       return false;
185     }
186
187     if (occurrences[1].equals(1)) {
188       return true;
189     }
190     occurrences[1] = (Integer) occurrences[1] - 1;
191     return false;
192   }
193
194   /*
195     node template with type equal to node type or derived from node type
196      */
197   @Override
198   public Map<String, NodeTemplate> getNodeTemplatesByType(ServiceTemplate serviceTemplate,
199                                                           String nodeType,
200                                                           ToscaServiceModel toscaServiceModel) {
201     Map<String, NodeTemplate> nodeTemplates = new HashMap<>();
202
203     if (Objects.nonNull(serviceTemplate.getTopology_template())
204         && MapUtils.isNotEmpty(serviceTemplate.getTopology_template().getNode_templates())) {
205       for (Map.Entry<String, NodeTemplate> nodeTemplateEntry : serviceTemplate
206           .getTopology_template().getNode_templates().entrySet()) {
207         if (isTypeOf(nodeTemplateEntry.getValue(), nodeType, serviceTemplate, toscaServiceModel)) {
208           nodeTemplates.put(nodeTemplateEntry.getKey(), nodeTemplateEntry.getValue());
209         }
210
211       }
212     }
213     return nodeTemplates;
214   }
215
216   @Override
217   public Optional<NodeType> fetchNodeType(String nodeTypeKey, Collection<ServiceTemplate>
218       serviceTemplates) {
219     Optional<Map<String, NodeType>> nodeTypeMap = serviceTemplates.stream()
220         .map(st -> st.getNode_types())
221         .filter(nodeTypes -> Objects.nonNull(nodeTypes) && nodeTypes.containsKey(nodeTypeKey))
222         .findFirst();
223     if (nodeTypeMap.isPresent()) {
224       return Optional.ofNullable(nodeTypeMap.get().get(nodeTypeKey));
225     }
226     return Optional.empty();
227   }
228
229   @Override
230   public boolean isTypeOf(NodeTemplate nodeTemplate, String nodeType,
231                           ServiceTemplate serviceTemplate, ToscaServiceModel toscaServiceModel) {
232     if (nodeTemplate == null) {
233       return false;
234     }
235
236     if (isNodeTemplateOfTypeNodeType(nodeTemplate, nodeType)) {
237       return true;
238     }
239
240     Optional<Boolean> nodeTypeExistInServiceTemplateHierarchy =
241         isNodeTypeExistInServiceTemplateHierarchy(nodeType, nodeTemplate.getType(), serviceTemplate,
242             toscaServiceModel, null);
243     return nodeTypeExistInServiceTemplateHierarchy.orElseThrow(() -> new CoreException(
244         new ToscaNodeTypeNotFoundErrorBuilder(nodeTemplate.getType()).build()));
245   }
246
247   @Override
248   public List<RequirementAssignment> getRequirements(NodeTemplate nodeTemplate,
249                                                      String requirementId) {
250     List<RequirementAssignment> requirements = new ArrayList<>();
251     List<Map<String, RequirementAssignment>> requirementList = nodeTemplate.getRequirements();
252     if (requirementList != null) {
253       requirementList.stream().filter(reqMap -> reqMap.get(requirementId) != null)
254           .forEach(reqMap -> {
255             ToscaExtensionYamlUtil toscaExtensionYamlUtil = new ToscaExtensionYamlUtil();
256             RequirementAssignment reqAssignment = toscaExtensionYamlUtil
257                 .yamlToObject(toscaExtensionYamlUtil.objectToYaml(reqMap.get(requirementId)),
258                     RequirementAssignment.class);
259             requirements.add(reqAssignment);
260           });
261     }
262     return requirements;
263   }
264
265   @Override
266   public Optional<NodeTemplate> getNodeTemplateById(ServiceTemplate serviceTemplate,
267                                                     String nodeTemplateId) {
268     if ((serviceTemplate.getTopology_template() != null)
269         && (serviceTemplate.getTopology_template().getNode_templates() != null)
270         && (serviceTemplate.getTopology_template().getNode_templates().get(nodeTemplateId)
271         != null)) {
272       return Optional
273           .of(serviceTemplate.getTopology_template().getNode_templates().get(nodeTemplateId));
274     }
275     return Optional.empty();
276   }
277
278   @Override
279   public Optional<String> getSubstituteServiceTemplateName(String substituteNodeTemplateId,
280                                                            NodeTemplate substitutableNodeTemplate) {
281     if (!isSubstitutableNodeTemplate(substitutableNodeTemplate)) {
282       return Optional.empty();
283     }
284
285     if (substitutableNodeTemplate.getProperties() != null
286         && substitutableNodeTemplate.getProperties()
287         .get(ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME) != null) {
288       Object serviceTemplateFilter = substitutableNodeTemplate.getProperties()
289           .get(ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME);
290       if (serviceTemplateFilter != null && serviceTemplateFilter instanceof Map) {
291         Object substituteServiceTemplate = ((Map) serviceTemplateFilter)
292             .get(ToscaConstants.SUBSTITUTE_SERVICE_TEMPLATE_PROPERTY_NAME);
293         if (substituteServiceTemplate == null) {
294           MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
295               LoggerTragetServiceName.ADD_ENTITIES_TO_TOSCA, ErrorLevel.ERROR.name(),
296               LoggerErrorCode.DATA_ERROR.getErrorCode(), LoggerErrorDescription.INVALID_PROPERTY);
297           throw new CoreException(
298               new ToscaInvalidSubstituteNodeTemplatePropertiesErrorBuilder(substituteNodeTemplateId)
299                   .build());
300         }
301         return Optional.of(substituteServiceTemplate.toString());
302       }
303     }
304     MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
305         LoggerTragetServiceName.ADD_ENTITIES_TO_TOSCA, ErrorLevel.ERROR.name(),
306         LoggerErrorCode.DATA_ERROR.getErrorCode(), LoggerErrorDescription.INVALID_PROPERTY);
307     throw new CoreException(
308         new ToscaInvalidSubstituteNodeTemplatePropertiesErrorBuilder(substituteNodeTemplateId)
309             .build());
310   }
311
312   @Override
313   public Map<String, NodeTemplate> getSubstitutableNodeTemplates(ServiceTemplate serviceTemplate) {
314     Map<String, NodeTemplate> substitutableNodeTemplates = new HashMap<>();
315
316     if (serviceTemplate == null
317         || serviceTemplate.getTopology_template() == null
318         || serviceTemplate.getTopology_template().getNode_templates() == null) {
319       return substitutableNodeTemplates;
320     }
321
322     Map<String, NodeTemplate> nodeTemplates =
323         serviceTemplate.getTopology_template().getNode_templates();
324     for (String nodeTemplateId : nodeTemplates.keySet()) {
325       NodeTemplate nodeTemplate = nodeTemplates.get(nodeTemplateId);
326       if (isSubstitutableNodeTemplate(nodeTemplate)) {
327         substitutableNodeTemplates.put(nodeTemplateId, nodeTemplate);
328       }
329     }
330
331     return substitutableNodeTemplates;
332   }
333
334   @Override
335   public Optional<Map.Entry<String, NodeTemplate>> getSubstitutionMappedNodeTemplateByExposedReq(
336       String substituteServiceTemplateFileName, ServiceTemplate substituteServiceTemplate,
337       String requirementId) {
338     if (isSubstitutionServiceTemplate(substituteServiceTemplateFileName,
339         substituteServiceTemplate)) {
340       Map<String, List<String>> substitutionMappingRequirements =
341           substituteServiceTemplate.getTopology_template().getSubstitution_mappings()
342               .getRequirements();
343       if (substitutionMappingRequirements != null) {
344         List<String> requirementMapping = substitutionMappingRequirements.get(requirementId);
345         if (requirementMapping != null && !requirementMapping.isEmpty()) {
346           String mappedNodeTemplateId = requirementMapping.get(0);
347           Optional<NodeTemplate> mappedNodeTemplate =
348               getNodeTemplateById(substituteServiceTemplate, mappedNodeTemplateId);
349           mappedNodeTemplate.orElseThrow(() -> new CoreException(
350               new ToscaInvalidEntryNotFoundErrorBuilder("Node Template", mappedNodeTemplateId)
351                   .build()));
352           Map.Entry<String, NodeTemplate> mappedNodeTemplateEntry =
353               new Map.Entry<String, NodeTemplate>() {
354                 @Override
355                 public String getKey() {
356                   return mappedNodeTemplateId;
357                 }
358
359                 @Override
360                 public NodeTemplate getValue() {
361                   return mappedNodeTemplate.get();
362                 }
363
364                 @Override
365                 public NodeTemplate setValue(NodeTemplate value) {
366                   return null;
367                 }
368               };
369           return Optional.of(mappedNodeTemplateEntry);
370         }
371       }
372     }
373     return Optional.empty();
374   }
375
376   /*
377   match only for the input which is not null
378    */
379   @Override
380   public boolean isDesiredRequirementAssignment(RequirementAssignment requirementAssignment,
381                                                 String capability, String node,
382                                                 String relationship) {
383     if (capability != null) {
384       if (requirementAssignment.getCapability() == null
385           || !requirementAssignment.getCapability().equals(capability)) {
386         return false;
387       }
388     }
389
390     if (node != null) {
391       if (requirementAssignment.getNode() == null
392           || !requirementAssignment.getNode().equals(node)) {
393         return false;
394       }
395     }
396
397     if (relationship != null) {
398       if (requirementAssignment.getRelationship() == null
399           || !requirementAssignment.getRelationship().equals(relationship)) {
400         return false;
401       }
402     }
403
404     return !(capability == null && node == null && relationship == null);
405
406   }
407
408   @Override
409   public Object getFlatEntity(ToscaElementTypes elementType, String typeId,
410                               ServiceTemplate serviceTemplate, ToscaServiceModel toscaModel) {
411     Object returnEntity;
412
413     switch (elementType) {
414       case CAPABILITY_TYPE:
415         returnEntity = new CapabilityType();
416         break;
417       case NODE_TYPE:
418         returnEntity = new NodeType();
419         break;
420       default:
421         MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
422             LoggerTragetServiceName.ADD_ENTITIES_TO_TOSCA, ErrorLevel.ERROR.name(),
423             LoggerErrorCode.DATA_ERROR.getErrorCode(), LoggerErrorDescription.UNSUPPORTED_ENTITY);
424         throw new RuntimeException(
425             "Entity[" + elementType + "] id[" + typeId + "] flat not supported");
426     }
427
428     scanAnFlatEntity(elementType, typeId, returnEntity, serviceTemplate, toscaModel,
429         new ArrayList<String>(), 0);
430
431
432     return returnEntity;
433   }
434
435   @Override
436   public boolean isSubstitutableNodeTemplate(NodeTemplate nodeTemplate) {
437     return nodeTemplate.getDirectives() != null
438         && nodeTemplate.getDirectives().contains(ToscaConstants
439         .NODE_TEMPLATE_DIRECTIVE_SUBSTITUTABLE);
440   }
441
442   private Optional<Boolean> isNodeTypeExistInServiceTemplateHierarchy(
443       String nodeTypeToMatch,
444       String nodeTypeToSearch,
445       ServiceTemplate serviceTemplate,
446       ToscaServiceModel toscaServiceModel,
447       Set<String> analyzedImportFiles) {
448     Map<String, NodeType> searchableNodeTypes = serviceTemplate.getNode_types();
449     if (!MapUtils.isEmpty(searchableNodeTypes)) {
450       NodeType nodeType = searchableNodeTypes.get(nodeTypeToSearch);
451       if (Objects.nonNull(nodeType)) {
452         if (Objects.equals(nodeType.getDerived_from(), nodeTypeToMatch)) {
453           return Optional.of(true);
454         } else if (isNodeTypeIsToscaRoot(nodeType)) {
455           return Optional.of(false);
456         } else {
457           return isNodeTypeExistInServiceTemplateHierarchy(nodeTypeToMatch,
458               nodeType.getDerived_from(), serviceTemplate, toscaServiceModel, null);
459         }
460       } else {
461         return isNodeTypeExistInImports(nodeTypeToMatch, nodeTypeToSearch, serviceTemplate,
462             toscaServiceModel, analyzedImportFiles);
463       }
464     }
465     return isNodeTypeExistInImports(nodeTypeToMatch, nodeTypeToSearch, serviceTemplate,
466         toscaServiceModel, analyzedImportFiles);
467
468   }
469
470   private Optional<Boolean> isNodeTypeExistInImports(String nodeTypeToMatch,
471                                                      String nodeTypeToSearch,
472                                                      ServiceTemplate serviceTemplate,
473                                                      ToscaServiceModel toscaServiceModel,
474                                                      Set<String> filesScanned) {
475     List<Map<String, Import>> imports = serviceTemplate.getImports();
476     if (CollectionUtils.isEmpty(imports)) {
477       return Optional.empty();
478     }
479
480     filesScanned = createFilesScannedSet(filesScanned);
481
482     for (Map<String, Import> map : imports) {
483       ToscaExtensionYamlUtil toscaExtensionYamlUtil = new ToscaExtensionYamlUtil();
484       Import anImport = toscaExtensionYamlUtil
485           .yamlToObject(toscaExtensionYamlUtil.objectToYaml(map.values().iterator().next()),
486               Import.class);
487       if (Objects.isNull(anImport) || Objects.isNull(anImport.getFile())) {
488         throw new RuntimeException("import without file entry");
489       }
490       String importFile = anImport.getFile();
491       ServiceTemplate template =
492           toscaServiceModel.getServiceTemplates().get(fetchFileNameForImport(importFile,
493               serviceTemplate.getMetadata() == null ? null
494                   : serviceTemplate.getMetadata().get("filename")));
495       if (filesScanned.contains(ToscaUtil.getServiceTemplateFileName(template))) {
496         continue;
497       } else {
498         filesScanned.add(ToscaUtil.getServiceTemplateFileName(template));
499       }
500       Optional<Boolean> nodeTypeExistInServiceTemplateHierarchy =
501           isNodeTypeExistInServiceTemplateHierarchy(nodeTypeToMatch, nodeTypeToSearch, template,
502               toscaServiceModel, filesScanned);
503       if (nodeTypeExistInServiceTemplateHierarchy.isPresent()) {
504         if (nodeTypeExistInServiceTemplateHierarchy.get()) {
505           filesScanned.clear();
506           return Optional.of(true);
507         }
508       }
509
510     }
511     return Optional.of(false);
512   }
513
514   private Set<String> addImportFileToAnalyzedImportFilesSet(Set<String> analyzedImportFiles,
515                                                             String importFile) {
516     analyzedImportFiles.add(importFile);
517     return analyzedImportFiles;
518   }
519
520   private Set<String> createFilesScannedSet(Set<String> filesScanned) {
521     if (Objects.isNull(filesScanned)) {
522       filesScanned = new HashSet<>();
523     }
524     return filesScanned;
525   }
526
527   private boolean isNodeTypeIsToscaRoot(NodeType stNodeType) {
528     return Objects.equals(stNodeType.getDerived_from(), ToscaNodeType.NATIVE_ROOT);
529   }
530
531   private boolean isNodeTemplateOfTypeNodeType(NodeTemplate nodeTemplate, String nodeType) {
532     return Objects.equals(nodeTemplate.getType(), nodeType);
533   }
534
535   private boolean isSubstitutionServiceTemplate(String substituteServiceTemplateFileName,
536                                                 ServiceTemplate substituteServiceTemplate) {
537     if (substituteServiceTemplate != null
538         && substituteServiceTemplate.getTopology_template() != null
539         && substituteServiceTemplate.getTopology_template().getSubstitution_mappings() != null) {
540       if (substituteServiceTemplate.getTopology_template().getSubstitution_mappings()
541           .getNode_type() == null) {
542         throw new CoreException(new ToscaInvalidSubstitutionServiceTemplateErrorBuilder(
543             substituteServiceTemplateFileName).build());
544       }
545       return true;
546     }
547     return false;
548
549   }
550
551   private boolean scanAnFlatEntity(ToscaElementTypes elementType, String typeId, Object entity,
552                                    ServiceTemplate serviceTemplate, ToscaServiceModel toscaModel,
553                                    List<String> filesScanned, int rootScanStartInx) {
554
555
556     boolean entityFound =
557         enrichEntityFromCurrentServiceTemplate(elementType, typeId, entity, serviceTemplate,
558             toscaModel, filesScanned, rootScanStartInx);
559     if (!entityFound) {
560       List<Map<String, Import>> imports = serviceTemplate.getImports();
561       if (CollectionUtils.isEmpty(imports)) {
562         return false;
563       }
564       ToscaExtensionYamlUtil toscaExtensionYamlUtil = new ToscaExtensionYamlUtil();
565       boolean found = false;
566       for (Map<String, Import> importMap : imports) {
567         if (found) {
568           return true;
569         }
570         String filename = "";
571         for (Object importObject : importMap.values()) {
572           Import importServiceTemplate = toscaExtensionYamlUtil
573               .yamlToObject(toscaExtensionYamlUtil.objectToYaml(importObject), Import.class);
574           filename = fetchFileNameForImport(importServiceTemplate.getFile(),
575               serviceTemplate.getMetadata() == null ? null : serviceTemplate.getMetadata().get
576                   ("filename"));
577           if (filesScanned.contains(filename)) {
578             return false;
579           } else {
580             filesScanned.add(filename);
581           }
582           ServiceTemplate template =
583               toscaModel.getServiceTemplates()
584                   .get(filename);
585           found =
586               scanAnFlatEntity(elementType, typeId, entity, template, toscaModel, filesScanned,
587                   filesScanned.size());
588         }
589       }
590       return found;
591     }
592     return true;
593   }
594
595   private String fetchFileNameForImport(String importServiceTemplateFile,
596                                         String currentMetadatafileName) {
597     if (importServiceTemplateFile.contains("../")) {
598       return importServiceTemplateFile.replace("../", "");
599     } else if (importServiceTemplateFile.contains("/")) {
600       return importServiceTemplateFile;
601     } else if (currentMetadatafileName != null) {
602       return currentMetadatafileName.substring(0, currentMetadatafileName.indexOf("/")) + "/" +
603           importServiceTemplateFile;
604     } else {
605       return importServiceTemplateFile;
606     }
607
608   }
609
610   private boolean enrichEntityFromCurrentServiceTemplate(ToscaElementTypes elementType,
611                                                          String typeId, Object entity,
612                                                          ServiceTemplate serviceTemplate,
613                                                          ToscaServiceModel toscaModel,
614                                                          List<String> filesScanned,
615                                                          int rootScanStartInx) {
616     String derivedFrom;
617     switch (elementType) {
618       case CAPABILITY_TYPE:
619         if (serviceTemplate.getCapability_types() != null
620             && serviceTemplate.getCapability_types().containsKey(typeId)) {
621
622           filesScanned.clear();
623           CapabilityType targetCapabilityType = ((CapabilityType) entity);
624           CapabilityType sourceCapabilityType = serviceTemplate.getCapability_types().get(typeId);
625           derivedFrom = sourceCapabilityType.getDerived_from();
626           if (derivedFrom != null) {
627             scanAnFlatEntity(elementType, derivedFrom, entity, serviceTemplate, toscaModel,
628                 filesScanned, rootScanStartInx);
629           }
630           combineCapabilityTypeInfo(sourceCapabilityType, targetCapabilityType);
631         } else {
632           return false;
633         }
634         break;
635       case NODE_TYPE:
636         if (serviceTemplate.getNode_types() != null
637             && serviceTemplate.getNode_types().containsKey(typeId)) {
638
639           filesScanned.clear();
640           NodeType targetNodeType = ((NodeType) entity);
641           NodeType sourceNodeType = serviceTemplate.getNode_types().get(typeId);
642           derivedFrom = sourceNodeType.getDerived_from();
643           if (derivedFrom != null) {
644             scanAnFlatEntity(elementType, derivedFrom, entity, serviceTemplate, toscaModel,
645                 filesScanned, rootScanStartInx);
646           }
647           combineNodeTypeInfo(sourceNodeType, targetNodeType);
648         } else {
649           return false;
650         }
651         break;
652       default:
653         MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
654             LoggerTragetServiceName.ADD_ENTITIES_TO_TOSCA, ErrorLevel.ERROR.name(),
655             LoggerErrorCode.DATA_ERROR.getErrorCode(), LoggerErrorDescription.UNSUPPORTED_ENTITY);
656         throw new RuntimeException(
657             "Entity[" + elementType + "] id[" + typeId + "] flat not supported");
658     }
659
660     return true;
661
662
663   }
664
665   private void combineNodeTypeInfo(NodeType sourceNodeType, NodeType targetNodeType) {
666     targetNodeType.setDerived_from(sourceNodeType.getDerived_from());
667     targetNodeType.setDescription(sourceNodeType.getDescription());
668     targetNodeType.setVersion(sourceNodeType.getVersion());
669     targetNodeType.setProperties(
670         CommonMethods.mergeMaps(targetNodeType.getProperties(), sourceNodeType.getProperties()));
671     targetNodeType.setInterfaces(
672         CommonMethods.mergeMaps(targetNodeType.getInterfaces(), sourceNodeType.getInterfaces()));
673     targetNodeType.setArtifacts(
674         CommonMethods.mergeMaps(targetNodeType.getArtifacts(), sourceNodeType.getArtifacts()));
675     targetNodeType.setAttributes(
676         CommonMethods.mergeMaps(targetNodeType.getAttributes(), sourceNodeType.getAttributes()));
677     targetNodeType.setCapabilities(CommonMethods
678         .mergeMaps(targetNodeType.getCapabilities(), sourceNodeType.getCapabilities()));
679     targetNodeType.setRequirements(CommonMethods
680         .mergeListsOfMap(targetNodeType.getRequirements(), sourceNodeType.getRequirements()));
681
682   }
683
684
685   private void combineCapabilityTypeInfo(CapabilityType sourceCapabilityType,
686                                          CapabilityType targetCapabilityType) {
687
688     targetCapabilityType.setAttributes(CommonMethods
689         .mergeMaps(targetCapabilityType.getAttributes(), sourceCapabilityType.getAttributes()));
690     targetCapabilityType.setProperties(CommonMethods
691         .mergeMaps(targetCapabilityType.getProperties(), sourceCapabilityType.getProperties()));
692     targetCapabilityType.setValid_source_types(CommonMethods
693         .mergeLists(targetCapabilityType.getValid_source_types(),
694             sourceCapabilityType.getValid_source_types()));
695
696     if (!CommonMethods.isEmpty(sourceCapabilityType.getDerived_from())) {
697       targetCapabilityType.setDerived_from(sourceCapabilityType.getDerived_from());
698     }
699     if (!CommonMethods.isEmpty(sourceCapabilityType.getDescription())) {
700       targetCapabilityType.setDescription(sourceCapabilityType.getDescription());
701     }
702     if (!CommonMethods.isEmpty(sourceCapabilityType.getVersion())) {
703       targetCapabilityType.setVersion(sourceCapabilityType.getVersion());
704     }
705
706
707   }
708
709
710   /*
711  * Create node type according to the input substitution service template, while the substitution
712  * service template can be mappted to this node type, for substitution mapping.
713  *
714  * @param substitutionServiceTemplate  substitution serivce template
715  * @param nodeTypeDerivedFromValue derived from value for the created node type
716  * @return the node type
717  */
718   @Override
719   public NodeType createInitSubstitutionNodeType(ServiceTemplate substitutionServiceTemplate,
720                                                  String nodeTypeDerivedFromValue) {
721     NodeType substitutionNodeType = new NodeType();
722     substitutionNodeType.setDerived_from(nodeTypeDerivedFromValue);
723     substitutionNodeType.setDescription(substitutionServiceTemplate.getDescription());
724     substitutionNodeType
725         .setProperties(manageSubstitutionNodeTypeProperties(substitutionServiceTemplate));
726     substitutionNodeType
727         .setAttributes(manageSubstitutionNodeTypeAttributes(substitutionServiceTemplate));
728     return substitutionNodeType;
729   }
730
731   public Map<String, PropertyDefinition> manageSubstitutionNodeTypeProperties(
732       ServiceTemplate substitutionServiceTemplate) {
733     Map<String, PropertyDefinition> substitutionNodeTypeProperties = new HashMap<>();
734     Map<String, ParameterDefinition> properties =
735         substitutionServiceTemplate.getTopology_template().getInputs();
736     if (properties == null) {
737       return null;
738     }
739
740     PropertyDefinition propertyDefinition;
741     String toscaPropertyName;
742     for (Map.Entry<String, ParameterDefinition> entry : properties.entrySet()) {
743       toscaPropertyName = entry.getKey();
744       propertyDefinition = new PropertyDefinition();
745       ParameterDefinition parameterDefinition =
746           substitutionServiceTemplate.getTopology_template().getInputs().get(toscaPropertyName);
747       propertyDefinition.setType(parameterDefinition.getType());
748       propertyDefinition.setDescription(parameterDefinition.getDescription());
749       propertyDefinition.set_default(parameterDefinition.get_default());
750       if (parameterDefinition.getRequired() != null) {
751         propertyDefinition.setRequired(parameterDefinition.getRequired());
752       }
753       if (propertyDefinition.get_default() != null) {
754         propertyDefinition.setRequired(false);
755       }
756       if (!CollectionUtils.isEmpty(parameterDefinition.getConstraints())) {
757         propertyDefinition.setConstraints(parameterDefinition.getConstraints());
758       }
759       propertyDefinition.setEntry_schema(parameterDefinition.getEntry_schema());
760       if (parameterDefinition.getStatus() != null) {
761         propertyDefinition.setStatus(parameterDefinition.getStatus());
762       }
763       substitutionNodeTypeProperties.put(toscaPropertyName, propertyDefinition);
764     }
765     return substitutionNodeTypeProperties;
766   }
767
768   private Map<String, AttributeDefinition> manageSubstitutionNodeTypeAttributes(
769       ServiceTemplate substitutionServiceTemplate) {
770     Map<String, AttributeDefinition> substitutionNodeTypeAttributes = new HashMap<>();
771     Map<String, ParameterDefinition> attributes =
772         substitutionServiceTemplate.getTopology_template().getOutputs();
773     if (attributes == null) {
774       return null;
775     }
776     AttributeDefinition attributeDefinition;
777     String toscaAttributeName;
778
779     for (Map.Entry<String, ParameterDefinition> entry : attributes.entrySet()) {
780       attributeDefinition = new AttributeDefinition();
781       toscaAttributeName = entry.getKey();
782       ParameterDefinition parameterDefinition =
783           substitutionServiceTemplate.getTopology_template().getOutputs().get(toscaAttributeName);
784       if (parameterDefinition.getType() != null && !parameterDefinition.getType().isEmpty()) {
785         attributeDefinition.setType(parameterDefinition.getType());
786       } else {
787         attributeDefinition.setType(PropertyType.STRING.getDisplayName());
788       }
789       attributeDefinition.setDescription(parameterDefinition.getDescription());
790       attributeDefinition.set_default(parameterDefinition.get_default());
791       attributeDefinition.setEntry_schema(parameterDefinition.getEntry_schema());
792       if (Objects.nonNull(parameterDefinition.getStatus())) {
793         attributeDefinition.setStatus(parameterDefinition.getStatus());
794       }
795       substitutionNodeTypeAttributes.put(toscaAttributeName, attributeDefinition);
796     }
797     return substitutionNodeTypeAttributes;
798   }
799
800   /**
801    * Checks if the requirement exists in the node template.
802    *
803    * @param nodeTemplate          the node template
804    * @param requirementId         the requirement id
805    * @param requirementAssignment the requirement assignment
806    * @return true if the requirement already exists and false otherwise
807    */
808   public boolean isRequirementExistInNodeTemplate(NodeTemplate nodeTemplate,
809                                                   String requirementId,
810                                                   RequirementAssignment requirementAssignment) {
811     boolean result = false;
812     List<Map<String, RequirementAssignment>> nodeTemplateRequirements = nodeTemplate
813         .getRequirements();
814     if (nodeTemplateRequirements != null) {
815       for (Map<String, RequirementAssignment> requirement : nodeTemplateRequirements) {
816         if (requirement.containsKey(requirementId)) {
817           result = DataModelUtil.compareRequirementAssignment(requirementAssignment,
818               requirement.get(requirementId));
819           if (result) {
820             break;
821           }
822         }
823       }
824     }
825     return result;
826   }
827 }