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