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