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